diff --git a/Arduino/SelfomatController/AgreementState.cpp b/Arduino/SelfomatController/AgreementState.cpp new file mode 100644 index 0000000..d86a339 --- /dev/null +++ b/Arduino/SelfomatController/AgreementState.cpp @@ -0,0 +1,73 @@ +#include "AgreementState.h" +#include "IdleState.h" + +AgreementState AgreementState::INSTANCE; + +bool AgreementState::processCommand(const uint8_t* buffer, size_t size) { + // Handle 'a' since we're already in agreement + if(size == 1 && buffer[0] == 'a') { + sendCommand('A'); + return true; + } + + // Process base commands. + if(BaseState::processCommand(buffer, size)) + return true; + + return false; +} + +void AgreementState::animationStep(unsigned long dt) { + // Fade + if (shouldExit) { + if (b > 0.0) { + b -= min(b, 0.025); + } else { + exitAnimationDone = true; + } + } else { + if (b < 1.0) { + b += min(1-b, 0.01); + } + } + + + float angleOffset = timeInState()/300.0f; + float anglePerLed = (2.0 * PI) / ring.numPixels(); + for(int j = 0; j < ring.numPixels(); j++) { + float angle = (float)j * anglePerLed + angleOffset; + float sin_x = sin(angle); + uint8_t brightness = sin_x*sin_x * 255.0f * b; + ring.setPixelColor(j, 0, brightness, 0); + } + ring.show(); +} + +BaseState* AgreementState::logicStep() { + if(!shouldExit && digitalRead(PIN_BUTTON) == LOW) { + shouldExit = true; + sendCommand('c'); + } + + if(shouldExit && exitAnimationDone) { + sendCommand('a'); + return &IdleState::INSTANCE; + } + return this; +} + +void AgreementState::enter() { + BaseState::enter(); + b = 0; + frame = 0; + exitAnimationDone = shouldExit = false; + sendCommand('A'); +} + +void AgreementState::exit() { + +} + +bool AgreementState::needsHeartbeat() { + return !heartbeatDeactivated; +} diff --git a/Arduino/SelfomatController/AgreementState.h b/Arduino/SelfomatController/AgreementState.h new file mode 100644 index 0000000..5aea90e --- /dev/null +++ b/Arduino/SelfomatController/AgreementState.h @@ -0,0 +1,44 @@ +#ifndef AGREEMENT_STATE_H +#define AGREEMENT_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class AgreementState : public BaseState { +private: + uint8_t frame; + float b; + bool shouldExit; + bool exitAnimationDone; +public: + static AgreementState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/BootingState.cpp b/Arduino/SelfomatController/BootingState.cpp new file mode 100644 index 0000000..f1ccedb --- /dev/null +++ b/Arduino/SelfomatController/BootingState.cpp @@ -0,0 +1,68 @@ +#include "BootingState.h" +#include "IdleState.h" + +BootingState BootingState::INSTANCE; + +bool BootingState::processCommand(const uint8_t* buffer, size_t size) { + bool parentHandled = BaseState::processCommand(buffer, size); + // If it was a heartbeat, we want to exit + if (size == 1 && buffer[0] == '.') { + shouldExit = true; + return true; + } + return parentHandled; +} + +void BootingState::animationStep(unsigned long dt) { + // Fade + if (shouldExit) { + if (b > 0) { + b-=min(b,4); + } else { + exitAnimationDone = true; + } + } else { + if (b < 255) { + b+=min(4, 255-b); + } + } + + // Animate + for (int i = 0; i < ring.numPixels(); i++) { + byte diff = (i - frame) % ring.numPixels(); + byte color = (b / ring.numPixels() * diff); + ring.setPixelColor(i, 0, color, color >> 2); + } + ring.show(); + + // Skip to next frame + frame++; +} + +BaseState* BootingState::logicStep() { + BaseState* parentStep = BaseState::logicStep(); + if(parentStep) + return parentStep; + + if(shouldExit && exitAnimationDone) { + return &IdleState::INSTANCE; + } + + return this; +} + +void BootingState::enter() { + frame = 0; + exitAnimationDone = shouldExit = false; +} + +void BootingState::exit() { + // Booting done, we need a heartbeat. Assume we got it now + heartbeatDeactivated = false; + lastHeartbeat = millis(); +} + +bool BootingState::needsHeartbeat() { + // Booting so no heartbeat required + return false; +} diff --git a/Arduino/SelfomatController/BootingState.h b/Arduino/SelfomatController/BootingState.h new file mode 100644 index 0000000..13409ef --- /dev/null +++ b/Arduino/SelfomatController/BootingState.h @@ -0,0 +1,44 @@ +#ifndef BOOTING_STATE_H +#define BOOTING_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class BootingState: public BaseState { +private: + uint32_t frame = 0; + int b = 0; + bool shouldExit; + bool exitAnimationDone; +public: + static BootingState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/BusyState.cpp b/Arduino/SelfomatController/BusyState.cpp new file mode 100644 index 0000000..af13901 --- /dev/null +++ b/Arduino/SelfomatController/BusyState.cpp @@ -0,0 +1,75 @@ +#include "BusyState.h" +#include "IdleState.h" +#include "PrintingState.h" +#include "PinChangeInterrupt.h" + +BusyState BusyState::INSTANCE; + +bool BusyState::processCommand(const uint8_t* buffer, size_t size) { + if(BaseState::processCommand(buffer, size)) + return true; + + if(size == 1) { + switch(buffer[0]) { + case 'k': + exitIdle = true; + return true; + case 'p': + exitPrint = true; + return true; + default: + return false; + } + } + return false; +} + +void BusyState::animationStep(unsigned long dt) { + // No animation here! +} + +BaseState* BusyState::logicStep() { + + if(flashTriggered) { + if(settings.flashDurationMicros < 0) { + delay(10); + } else { + while(micros() - flashStartMicros < settings.flashDurationMicros); + } + digitalWrite(PIN_FLASH_ON, LOW); + flashTriggered = false; + } + + // timeout in busy state + if(timeInState() > 15000 || exitIdle) { + return &IdleState::INSTANCE; + } + if(exitPrint) { + return &PrintingState::INSTANCE; + } + return this; +} + +void BusyState::enter() { + BaseState::enter(); + flashTriggered = exitPrint = exitIdle = false; + attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(PIN_FLASH_CAM_TRIGGER), triggerFlash, FALLING); +} + +void BusyState::exit() { + // first, detach the interrupt!! + detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(PIN_FLASH_CAM_TRIGGER)); + // then turn off the light for safety + digitalWrite(PIN_FLASH_ON, LOW); +} + +bool BusyState::needsHeartbeat() { + return !heartbeatDeactivated; +} + + +void BusyState::triggerFlash() { + PORTB |= 0b1000; + flashTriggered = true; + flashStartMicros = micros(); +} diff --git a/Arduino/SelfomatController/BusyState.h b/Arduino/SelfomatController/BusyState.h new file mode 100644 index 0000000..08ab06f --- /dev/null +++ b/Arduino/SelfomatController/BusyState.h @@ -0,0 +1,51 @@ +#ifndef BUSY_STATE_H +#define BUSY_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +// Storage for flash ISR +static volatile unsigned long flashStartMicros; +static volatile bool flashTriggered; + +class BusyState : public BaseState { +private: + + + + + bool exitPrint, exitIdle; +public: + static BusyState INSTANCE; + + static void triggerFlash(); + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/CountDownState.cpp b/Arduino/SelfomatController/CountDownState.cpp new file mode 100644 index 0000000..e511dc5 --- /dev/null +++ b/Arduino/SelfomatController/CountDownState.cpp @@ -0,0 +1,61 @@ +#include "CountDownState.h" +#include "BusyState.h" + +CountDownState CountDownState::INSTANCE; + +bool CountDownState::processCommand(const uint8_t* buffer, size_t size) { + // Process base commands. No fancy extras needed + return BaseState::processCommand(buffer, size); +} + +void CountDownState::animationStep(unsigned long dt) { + uint32_t color = colors[animationCycle]; + float percentage = ((float)timeInState() - animationCycle * oneCycleMillis) / oneCycleMillis; + + float pixelBorder = ring.numPixels() - ring.numPixels() * percentage; + + for(int8_t i=0; i pixelBorder) { + ring.setPixelColor((i+settings.ledOffset)%ring.numPixels(), color); + } else { + ring.setPixelColor((i+settings.ledOffset)%ring.numPixels(), lastColor); + } + } + ring.show(); + + if(percentage >= 1.0f) { + lastColor = color; + animationCycle++; + if(animationCycle > 2) { + animationCycle = 2; + } + } +} + +BaseState* CountDownState::logicStep() { + if(timeInState() > settings.countDownMillis) { + // Trigger the capture and go to idle + sendCommand('t'); + return &BusyState::INSTANCE; + } + return this; +} + +void CountDownState::enter() { + BaseState::enter(); + oneCycleMillis = (settings.countDownMillis)/3.0f; + animationCycle = 0; + lastColor = 0; +} + +void CountDownState::exit() { + for(int8_t i=0; i +// Copyright (c) 2011 Jacques Fortier +// +// SPDX-License-Identifier: MIT +// + + +#pragma once + + +#include "Arduino.h" + + +/// \brief A Consistent Overhead Byte Stuffing (COBS) Encoder. +/// +/// Consistent Overhead Byte Stuffing (COBS) is an encoding that removes all 0 +/// bytes from arbitrary binary data. The encoded data consists only of bytes +/// with values from 0x01 to 0xFF. This is useful for preparing data for +/// transmission over a serial link (RS-232 or RS-485 for example), as the 0 +/// byte can be used to unambiguously indicate packet boundaries. COBS also has +/// the advantage of adding very little overhead (at least 1 byte, plus up to an +/// additional byte per 254 bytes of data). For messages smaller than 254 bytes, +/// the overhead is constant. +/// +/// \sa http://conferences.sigcomm.org/sigcomm/1997/papers/p062.pdf +/// \sa http://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing +/// \sa https://github.com/jacquesf/COBS-Consistent-Overhead-Byte-Stuffing +/// \sa http://www.jacquesf.com/2011/03/consistent-overhead-byte-stuffing +class COBS +{ +public: + /// \brief Encode a byte buffer with the COBS encoder. + /// \param buffer A pointer to the unencoded buffer to encode. + /// \param size The number of bytes in the \p buffer. + /// \param encodedBuffer The buffer for the encoded bytes. + /// \returns The number of bytes written to the \p encodedBuffer. + /// \warning The encodedBuffer must have at least getEncodedBufferSize() allocated. + static size_t encode(const uint8_t* buffer, + size_t size, + uint8_t* encodedBuffer) + { + size_t read_index = 0; + size_t write_index = 1; + size_t code_index = 0; + uint8_t code = 1; + + while (read_index < size) + { + if (buffer[read_index] == ' ') + { + encodedBuffer[code_index] = code; + code = 1; + code_index = write_index++; + read_index++; + } + else + { + encodedBuffer[write_index++] = buffer[read_index++]; + code++; + + if (code == 0xFF) + { + encodedBuffer[code_index] = code; + code = 1; + code_index = write_index++; + } + } + } + + encodedBuffer[code_index] = code; + + return write_index; + } + + + /// \brief Decode a COBS-encoded buffer. + /// \param encodedBuffer A pointer to the \p encodedBuffer to decode. + /// \param size The number of bytes in the \p encodedBuffer. + /// \param decodedBuffer The target buffer for the decoded bytes. + /// \returns The number of bytes written to the \p decodedBuffer. + /// \warning decodedBuffer must have a minimum capacity of size. + static size_t decode(const uint8_t* encodedBuffer, + size_t size, + uint8_t* decodedBuffer) + { + if (size == 0) + return 0; + + size_t read_index = 0; + size_t write_index = 0; + uint8_t code = 0; + uint8_t i = 0; + + while (read_index < size) + { + code = encodedBuffer[read_index]; + + if (read_index + code > size && code != 1) + { + return 0; + } + + read_index++; + + for (i = 1; i < code; i++) + { + decodedBuffer[write_index++] = encodedBuffer[read_index++]; + } + + if (code != 0xFF && read_index != size) + { + decodedBuffer[write_index++] = ' '; + } + } + + return write_index; + } + + /// \brief Get the maximum encoded buffer size needed for a given unencoded buffer size. + /// \param unencodedBufferSize The size of the buffer to be encoded. + /// \returns the maximum size of the required encoded buffer. + static size_t getEncodedBufferSize(size_t unencodedBufferSize) + { + return unencodedBufferSize + unencodedBufferSize / 254 + 1; + } + +}; diff --git a/Arduino/SelfomatController/Encoding/SLIP.h b/Arduino/SelfomatController/Encoding/SLIP.h new file mode 100644 index 0000000..b70f4d0 --- /dev/null +++ b/Arduino/SelfomatController/Encoding/SLIP.h @@ -0,0 +1,141 @@ +// +// Copyright (c) 2010 Christopher Baker +// Copyright (c) 2016 Antoine Villeret +// +// SPDX-License-Identifier: MIT +// + + +#pragma once + + +#include "Arduino.h" + + +/// \brief A Serial Line IP (SLIP) Encoder. +/// +/// Serial Line IP (SLIP) is a packet framing protocol: SLIP defines a sequence +/// of characters that frame IP packets on a serial line and nothing more. It +/// provides no addressing, packet type identification, error detection, +/// correction or compression mechanisms. Because the protocol does so little +/// its implementation is trivial and fast. +/// +/// \sa http://tools.ietf.org/html/rfc1055 +class SLIP +{ +public: + /// \brief Encode a byte buffer with the SLIP encoder. + /// \param buffer A pointer to the unencoded buffer to encode. + /// \param size The number of bytes in the \p buffer. + /// \param encodedBuffer The buffer for the encoded bytes. + /// \returns The number of bytes written to the \p encodedBuffer. + /// \warning The encodedBuffer must have at least getEncodedBufferSize() allocated. + static size_t encode(const uint8_t* buffer, + size_t size, + uint8_t* encodedBuffer) + { + if (size == 0) + return 0; + + size_t read_index = 0; + size_t write_index = 0; + + // double-ENDed, flush any data that may have accumulated due to line noise + encodedBuffer[write_index++] = END; + + while (read_index < size) + { + if(buffer[read_index] == END) + { + encodedBuffer[write_index++] = ESC; + encodedBuffer[write_index++] = ESC_END; + read_index++; + } + else if(buffer[read_index] == ESC) + { + encodedBuffer[write_index++] = ESC; + encodedBuffer[write_index++] = ESC_ESC; + read_index++; + } + else + { + encodedBuffer[write_index++] = buffer[read_index++]; + } + } + + return write_index; + } + + /// \brief Decode a SLIP-encoded buffer. + /// \param encodedBuffer A pointer to the \p encodedBuffer to decode. + /// \param size The number of bytes in the \p encodedBuffer. + /// \param decodedBuffer The target buffer for the decoded bytes. + /// \returns The number of bytes written to the \p decodedBuffer. + /// \warning decodedBuffer must have a minimum capacity of size. + static size_t decode(const uint8_t* encodedBuffer, + size_t size, + uint8_t* decodedBuffer) + { + if (size == 0) + return 0; + + size_t read_index = 0; + size_t write_index = 0; + + while (read_index < size) + { + if (encodedBuffer[read_index] == END) + { + // flush or done + read_index++; + } + else if (encodedBuffer[read_index] == ESC) + { + if (encodedBuffer[read_index+1] == ESC_END) + { + decodedBuffer[write_index++] = END; + read_index += 2; + } + else if (encodedBuffer[read_index+1] == ESC_ESC) + { + decodedBuffer[write_index++] = ESC; + read_index += 2; + } + else + { + // considered a protocol violation + } + } + else + { + decodedBuffer[write_index++] = encodedBuffer[read_index++]; + } + } + + return write_index; + } + + /// \brief Get the maximum encoded buffer size needed for a given unencoded buffer size. + /// + /// SLIP has a start and a end markers (192 and 219). Marker value is + /// replaced by 2 bytes in the encoded buffer. So in the worst case of + /// sending a buffer with only '192' or '219', the encoded buffer length + /// will be 2 * buffer.size() + 2 + /// + /// \param unencodedBufferSize The size of the buffer to be encoded. + /// \returns the maximum size of the required encoded buffer. + static size_t getEncodedBufferSize(size_t unencodedBufferSize) + { + return unencodedBufferSize * 2 + 2; + } + + /// \brief Key constants used in the SLIP protocol. + enum + { + END = 0300, + ESC = 0333, + ESC_END = 0334, + ESC_ESC = 0335 + }; + +}; diff --git a/Arduino/SelfomatController/FastCRC.h b/Arduino/SelfomatController/FastCRC.h new file mode 100644 index 0000000..9ec9926 --- /dev/null +++ b/Arduino/SelfomatController/FastCRC.h @@ -0,0 +1,155 @@ +/* FastCRC library code is placed under the MIT license + * Copyright (c) 2014,2015 Frank Bösing + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +// Teensy 3.0, Teensy 3.1: +// See K20P64M72SF1RM.pdf (Kinetis), Pages 638 - 641 for documentation of CRC Device +// See KINETIS_4N30D.pdf for Errata (Errata ID 2776) +// +// So, ALL HW-calculations are done as 32 bit. +// +// +// +// Thanks to: +// - Catalogue of parametrised CRC algorithms, CRC RevEng +// http://reveng.sourceforge.net/crc-catalogue/ +// +// - Danjel McGougan (CRC-Table-Generator) +// + + +// Set this to 0 for smaller 32BIT-CRC-Tables: +#define CRC_BIGTABLES 1 + + +#if !defined(FastCRC_h) +#define FastCRC_h +#include "inttypes.h" + + +// ================= DEFINES =================== +#if defined(KINETISK) +#define CRC_SW 0 +#define CRC_FLAG_NOREFLECT (((1<<31) | (1<<30)) | ((0<<29) | (0<<28))) //refin=false refout=false +#define CRC_FLAG_REFLECT (((1<<31) | (0<<30)) | ((1<<29) | (0<<28))) //Reflect in- and outgoing bytes (refin=true refout=true) +#define CRC_FLAG_XOR (1<<26) //Perform XOR on result +#define CRC_FLAG_NOREFLECT_8 (0) //For 8-Bit CRC +#define CRC_FLAG_REFLECT_SWAP (((1<<31) | (0<<30)) | ((0<<29) | (1<<28))) //For 16-Bit CRC (byteswap) +#else +#define CRC_SW 1 +#endif + +// ================= 7-BIT CRC =================== +class FastCRC7 +{ +public: + FastCRC7(); + uint8_t crc7(const uint8_t *data, const uint16_t datalen); // (MultiMediaCard interface) + uint8_t crc7_upd(const uint8_t *data, const uint16_t datalen); // Call for subsequent calculations with previous seed. +#if !CRC_SW + uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen); //Not available in non-hw-variant (not T3.x) +#endif +private: +#if CRC_SW + uint8_t seed; +#else + uint8_t update(const uint8_t *data, const uint16_t datalen); +#endif +}; + +// ================= 8-BIT CRC =================== + +class FastCRC8 +{ +public: + FastCRC8(); + uint8_t smbus(const uint8_t *data, const uint16_t datalen); // Alias CRC-8 + uint8_t maxim(const uint8_t *data, const uint16_t datalen); // Equivalent to _crc_ibutton_update() in crc16.h from avr_libc + + uint8_t smbus_upd(const uint8_t *data, uint16_t datalen); // Call for subsequent calculations with previous seed. + uint8_t maxim_upd(const uint8_t *data, uint16_t datalen); // Call for subsequent calculations with previous seed. +#if !CRC_SW + uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen); //Not available in non-hw-variant (not T3.x) +#endif +private: +#if CRC_SW + uint8_t seed; +#else + uint8_t update(const uint8_t *data, const uint16_t datalen); +#endif +}; + +// ================= 16-BIT CRC =================== + +class FastCRC16 +{ +public: + FastCRC16(); + uint16_t ccitt(const uint8_t *data, const uint16_t datalen); // Alias "false CCITT" + uint16_t mcrf4xx(const uint8_t *data,const uint16_t datalen); // Equivalent to _crc_ccitt_update() in crc16.h from avr_libc + uint16_t kermit(const uint8_t *data, const uint16_t datalen); // Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT + uint16_t modbus(const uint8_t *data, const uint16_t datalen); // Equivalent to _crc_16_update() in crc16.h from avr_libc + uint16_t xmodem(const uint8_t *data, const uint16_t datalen); // Alias ZMODEM, CRC-16/ACORN + uint16_t x25(const uint8_t *data, const uint16_t datalen); // Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B + + uint16_t ccitt_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint16_t mcrf4xx_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint16_t kermit_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint16_t modbus_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint16_t xmodem_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint16_t x25_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed +#if !CRC_SW + uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen); //Not available in non-hw-variant (not T3.x) +#endif +private: +#if CRC_SW + uint16_t seed; +#else + uint16_t update(const uint8_t *data, const uint16_t datalen); +#endif +}; + +// ================= 32-BIT CRC =================== + +class FastCRC32 +{ +public: + FastCRC32(); + uint32_t crc32(const uint8_t *data, const uint16_t datalen); // Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3 + uint32_t cksum(const uint8_t *data, const uint16_t datalen); // Alias CRC-32/POSIX + + uint32_t crc32_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed + uint32_t cksum_upd(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed +#if !CRC_SW + uint32_t generic(const uint32_t polyom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen); //Not available in non-hw-variant (not T3.x) +#endif +private: +#if CRC_SW + uint32_t seed; +#else + uint32_t update(const uint8_t *data, const uint16_t datalen); +#endif +}; + +#endif diff --git a/Arduino/SelfomatController/FastCRC_cpu.h b/Arduino/SelfomatController/FastCRC_cpu.h new file mode 100644 index 0000000..1774e9b --- /dev/null +++ b/Arduino/SelfomatController/FastCRC_cpu.h @@ -0,0 +1,71 @@ +/* FastCRC library code is placed under the MIT license + * Copyright (c) 2014,2015,2016 Frank Bösing + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +// CPU-specific implementations of helper functions + +#if !defined(KINETISK) +#if !defined(FastCRC_cpu) +#define FastCRC_cpu + +//Reverse byte order (16 bit) +#if defined(__thumb__) +static inline __attribute__((always_inline)) +uint32_t REV16( uint32_t value) //ARM-THUMB +{ + asm ("rev16 %0, %1" : "=r" (value) : "r" (value) ); + return(value); +} +#else +static inline __attribute__((always_inline)) +uint32_t REV16( uint32_t value) //generic +{ + return (value >> 8) | ((value & 0xff) << 8); +} +#endif + + + + + +//Reverse byte order (32 bit) +#if defined(__thumb__) +static inline __attribute__((always_inline)) +uint32_t REV32( uint32_t value) //ARM-THUMB +{ + asm ("rev %0, %1" : "=r" (value) : "r" (value) ); + return(value); +} +#else +static inline __attribute__((always_inline)) +uint32_t REV32( uint32_t value) //generic +{ + value = (value >> 16) | ((value & 0xffff) << 16); + return ((value >> 8) & 0xff00ff) | ((value & 0xff00ff) << 8); +} +#endif + + +#endif +#endif diff --git a/Arduino/SelfomatController/FastCRC_tables.h b/Arduino/SelfomatController/FastCRC_tables.h new file mode 100644 index 0000000..0712d93 --- /dev/null +++ b/Arduino/SelfomatController/FastCRC_tables.h @@ -0,0 +1,1584 @@ +/* FastCRC library code is placed under the MIT license + * Copyright (c) 2014,2015 Frank Bösing + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + /* + Tables generated with universal_crc by Danjel McGougan + */ + + +#if !defined(FastCRC_tables) +#define FastCRC_tables +#include "inttypes.h" + +#if !defined(__SAM3X8E__) +#if defined(__AVR__ ) || defined(__IMXRT1052__) || defined(__IMXRT1062__) || defined(ARDUINO_ARCH_STM32F1) +#include +#else +#include +#endif +#endif + +const uint8_t crc_table_crc7[256] PROGMEM = { + 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, + 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee, + 0x32, 0x20, 0x16, 0x04, 0x7a, 0x68, 0x5e, 0x4c, + 0xa2, 0xb0, 0x86, 0x94, 0xea, 0xf8, 0xce, 0xdc, + 0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, + 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, + 0x56, 0x44, 0x72, 0x60, 0x1e, 0x0c, 0x3a, 0x28, + 0xc6, 0xd4, 0xe2, 0xf0, 0x8e, 0x9c, 0xaa, 0xb8, + 0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, + 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, + 0xfa, 0xe8, 0xde, 0xcc, 0xb2, 0xa0, 0x96, 0x84, + 0x6a, 0x78, 0x4e, 0x5c, 0x22, 0x30, 0x06, 0x14, + 0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, + 0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42, + 0x9e, 0x8c, 0xba, 0xa8, 0xd6, 0xc4, 0xf2, 0xe0, + 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x70, + 0x82, 0x90, 0xa6, 0xb4, 0xca, 0xd8, 0xee, 0xfc, + 0x12, 0x00, 0x36, 0x24, 0x5a, 0x48, 0x7e, 0x6c, + 0xb0, 0xa2, 0x94, 0x86, 0xf8, 0xea, 0xdc, 0xce, + 0x20, 0x32, 0x04, 0x16, 0x68, 0x7a, 0x4c, 0x5e, + 0xe6, 0xf4, 0xc2, 0xd0, 0xae, 0xbc, 0x8a, 0x98, + 0x76, 0x64, 0x52, 0x40, 0x3e, 0x2c, 0x1a, 0x08, + 0xd4, 0xc6, 0xf0, 0xe2, 0x9c, 0x8e, 0xb8, 0xaa, + 0x44, 0x56, 0x60, 0x72, 0x0c, 0x1e, 0x28, 0x3a, + 0x4a, 0x58, 0x6e, 0x7c, 0x02, 0x10, 0x26, 0x34, + 0xda, 0xc8, 0xfe, 0xec, 0x92, 0x80, 0xb6, 0xa4, + 0x78, 0x6a, 0x5c, 0x4e, 0x30, 0x22, 0x14, 0x06, + 0xe8, 0xfa, 0xcc, 0xde, 0xa0, 0xb2, 0x84, 0x96, + 0x2e, 0x3c, 0x0a, 0x18, 0x66, 0x74, 0x42, 0x50, + 0xbe, 0xac, 0x9a, 0x88, 0xf6, 0xe4, 0xd2, 0xc0, + 0x1c, 0x0e, 0x38, 0x2a, 0x54, 0x46, 0x70, 0x62, + 0x8c, 0x9e, 0xa8, 0xba, 0xc4, 0xd6, 0xe0, 0xf2 +}; + +const uint8_t crc_table_smbus[256] PROGMEM = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, + 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, + 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, + 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, + 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, + 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, + 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, + 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, + 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, + 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, + 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, + 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, + 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, + 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, + 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, + 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 +}; + +const uint8_t crc_table_maxim[256] PROGMEM = { + 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, + 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41, + 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, + 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc, + 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, + 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62, + 0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, + 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff, + 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, + 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07, + 0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, + 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a, + 0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, + 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24, + 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, + 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9, + 0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, + 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd, + 0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, + 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50, + 0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, + 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee, + 0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, + 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73, + 0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, + 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b, + 0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, + 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16, + 0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, + 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8, + 0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, + 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35 +}; + +const unsigned short crc_table_ccitt[1024] PROGMEM = { + 0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770, + 0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1, + 0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662, + 0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3, + 0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554, + 0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5, + 0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446, + 0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7, + 0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338, + 0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9, + 0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a, + 0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab, + 0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c, + 0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d, + 0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e, + 0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f, + 0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1, + 0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760, + 0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3, + 0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672, + 0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5, + 0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544, + 0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7, + 0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456, + 0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9, + 0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328, + 0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb, + 0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a, + 0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d, + 0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c, + 0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f, + 0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e, + 0x0000, 0x3133, 0x6266, 0x5355, 0xc4cc, 0xf5ff, 0xa6aa, 0x9799, + 0xa989, 0x98ba, 0xcbef, 0xfadc, 0x6d45, 0x5c76, 0x0f23, 0x3e10, + 0x7303, 0x4230, 0x1165, 0x2056, 0xb7cf, 0x86fc, 0xd5a9, 0xe49a, + 0xda8a, 0xebb9, 0xb8ec, 0x89df, 0x1e46, 0x2f75, 0x7c20, 0x4d13, + 0xe606, 0xd735, 0x8460, 0xb553, 0x22ca, 0x13f9, 0x40ac, 0x719f, + 0x4f8f, 0x7ebc, 0x2de9, 0x1cda, 0x8b43, 0xba70, 0xe925, 0xd816, + 0x9505, 0xa436, 0xf763, 0xc650, 0x51c9, 0x60fa, 0x33af, 0x029c, + 0x3c8c, 0x0dbf, 0x5eea, 0x6fd9, 0xf840, 0xc973, 0x9a26, 0xab15, + 0xcc0d, 0xfd3e, 0xae6b, 0x9f58, 0x08c1, 0x39f2, 0x6aa7, 0x5b94, + 0x6584, 0x54b7, 0x07e2, 0x36d1, 0xa148, 0x907b, 0xc32e, 0xf21d, + 0xbf0e, 0x8e3d, 0xdd68, 0xec5b, 0x7bc2, 0x4af1, 0x19a4, 0x2897, + 0x1687, 0x27b4, 0x74e1, 0x45d2, 0xd24b, 0xe378, 0xb02d, 0x811e, + 0x2a0b, 0x1b38, 0x486d, 0x795e, 0xeec7, 0xdff4, 0x8ca1, 0xbd92, + 0x8382, 0xb2b1, 0xe1e4, 0xd0d7, 0x474e, 0x767d, 0x2528, 0x141b, + 0x5908, 0x683b, 0x3b6e, 0x0a5d, 0x9dc4, 0xacf7, 0xffa2, 0xce91, + 0xf081, 0xc1b2, 0x92e7, 0xa3d4, 0x344d, 0x057e, 0x562b, 0x6718, + 0x981b, 0xa928, 0xfa7d, 0xcb4e, 0x5cd7, 0x6de4, 0x3eb1, 0x0f82, + 0x3192, 0x00a1, 0x53f4, 0x62c7, 0xf55e, 0xc46d, 0x9738, 0xa60b, + 0xeb18, 0xda2b, 0x897e, 0xb84d, 0x2fd4, 0x1ee7, 0x4db2, 0x7c81, + 0x4291, 0x73a2, 0x20f7, 0x11c4, 0x865d, 0xb76e, 0xe43b, 0xd508, + 0x7e1d, 0x4f2e, 0x1c7b, 0x2d48, 0xbad1, 0x8be2, 0xd8b7, 0xe984, + 0xd794, 0xe6a7, 0xb5f2, 0x84c1, 0x1358, 0x226b, 0x713e, 0x400d, + 0x0d1e, 0x3c2d, 0x6f78, 0x5e4b, 0xc9d2, 0xf8e1, 0xabb4, 0x9a87, + 0xa497, 0x95a4, 0xc6f1, 0xf7c2, 0x605b, 0x5168, 0x023d, 0x330e, + 0x5416, 0x6525, 0x3670, 0x0743, 0x90da, 0xa1e9, 0xf2bc, 0xc38f, + 0xfd9f, 0xccac, 0x9ff9, 0xaeca, 0x3953, 0x0860, 0x5b35, 0x6a06, + 0x2715, 0x1626, 0x4573, 0x7440, 0xe3d9, 0xd2ea, 0x81bf, 0xb08c, + 0x8e9c, 0xbfaf, 0xecfa, 0xddc9, 0x4a50, 0x7b63, 0x2836, 0x1905, + 0xb210, 0x8323, 0xd076, 0xe145, 0x76dc, 0x47ef, 0x14ba, 0x2589, + 0x1b99, 0x2aaa, 0x79ff, 0x48cc, 0xdf55, 0xee66, 0xbd33, 0x8c00, + 0xc113, 0xf020, 0xa375, 0x9246, 0x05df, 0x34ec, 0x67b9, 0x568a, + 0x689a, 0x59a9, 0x0afc, 0x3bcf, 0xac56, 0x9d65, 0xce30, 0xff03, + 0x0000, 0x3037, 0x606e, 0x5059, 0xc0dc, 0xf0eb, 0xa0b2, 0x9085, + 0xa1a9, 0x919e, 0xc1c7, 0xf1f0, 0x6175, 0x5142, 0x011b, 0x312c, + 0x6343, 0x5374, 0x032d, 0x331a, 0xa39f, 0x93a8, 0xc3f1, 0xf3c6, + 0xc2ea, 0xf2dd, 0xa284, 0x92b3, 0x0236, 0x3201, 0x6258, 0x526f, + 0xc686, 0xf6b1, 0xa6e8, 0x96df, 0x065a, 0x366d, 0x6634, 0x5603, + 0x672f, 0x5718, 0x0741, 0x3776, 0xa7f3, 0x97c4, 0xc79d, 0xf7aa, + 0xa5c5, 0x95f2, 0xc5ab, 0xf59c, 0x6519, 0x552e, 0x0577, 0x3540, + 0x046c, 0x345b, 0x6402, 0x5435, 0xc4b0, 0xf487, 0xa4de, 0x94e9, + 0xad1d, 0x9d2a, 0xcd73, 0xfd44, 0x6dc1, 0x5df6, 0x0daf, 0x3d98, + 0x0cb4, 0x3c83, 0x6cda, 0x5ced, 0xcc68, 0xfc5f, 0xac06, 0x9c31, + 0xce5e, 0xfe69, 0xae30, 0x9e07, 0x0e82, 0x3eb5, 0x6eec, 0x5edb, + 0x6ff7, 0x5fc0, 0x0f99, 0x3fae, 0xaf2b, 0x9f1c, 0xcf45, 0xff72, + 0x6b9b, 0x5bac, 0x0bf5, 0x3bc2, 0xab47, 0x9b70, 0xcb29, 0xfb1e, + 0xca32, 0xfa05, 0xaa5c, 0x9a6b, 0x0aee, 0x3ad9, 0x6a80, 0x5ab7, + 0x08d8, 0x38ef, 0x68b6, 0x5881, 0xc804, 0xf833, 0xa86a, 0x985d, + 0xa971, 0x9946, 0xc91f, 0xf928, 0x69ad, 0x599a, 0x09c3, 0x39f4, + 0x5a3b, 0x6a0c, 0x3a55, 0x0a62, 0x9ae7, 0xaad0, 0xfa89, 0xcabe, + 0xfb92, 0xcba5, 0x9bfc, 0xabcb, 0x3b4e, 0x0b79, 0x5b20, 0x6b17, + 0x3978, 0x094f, 0x5916, 0x6921, 0xf9a4, 0xc993, 0x99ca, 0xa9fd, + 0x98d1, 0xa8e6, 0xf8bf, 0xc888, 0x580d, 0x683a, 0x3863, 0x0854, + 0x9cbd, 0xac8a, 0xfcd3, 0xcce4, 0x5c61, 0x6c56, 0x3c0f, 0x0c38, + 0x3d14, 0x0d23, 0x5d7a, 0x6d4d, 0xfdc8, 0xcdff, 0x9da6, 0xad91, + 0xfffe, 0xcfc9, 0x9f90, 0xafa7, 0x3f22, 0x0f15, 0x5f4c, 0x6f7b, + 0x5e57, 0x6e60, 0x3e39, 0x0e0e, 0x9e8b, 0xaebc, 0xfee5, 0xced2, + 0xf726, 0xc711, 0x9748, 0xa77f, 0x37fa, 0x07cd, 0x5794, 0x67a3, + 0x568f, 0x66b8, 0x36e1, 0x06d6, 0x9653, 0xa664, 0xf63d, 0xc60a, + 0x9465, 0xa452, 0xf40b, 0xc43c, 0x54b9, 0x648e, 0x34d7, 0x04e0, + 0x35cc, 0x05fb, 0x55a2, 0x6595, 0xf510, 0xc527, 0x957e, 0xa549, + 0x31a0, 0x0197, 0x51ce, 0x61f9, 0xf17c, 0xc14b, 0x9112, 0xa125, + 0x9009, 0xa03e, 0xf067, 0xc050, 0x50d5, 0x60e2, 0x30bb, 0x008c, + 0x52e3, 0x62d4, 0x328d, 0x02ba, 0x923f, 0xa208, 0xf251, 0xc266, + 0xf34a, 0xc37d, 0x9324, 0xa313, 0x3396, 0x03a1, 0x53f8, 0x63cf, + 0x0000, 0xb476, 0x68ed, 0xdc9b, 0xf1ca, 0x45bc, 0x9927, 0x2d51, + 0xc385, 0x77f3, 0xab68, 0x1f1e, 0x324f, 0x8639, 0x5aa2, 0xeed4, + 0xa71b, 0x136d, 0xcff6, 0x7b80, 0x56d1, 0xe2a7, 0x3e3c, 0x8a4a, + 0x649e, 0xd0e8, 0x0c73, 0xb805, 0x9554, 0x2122, 0xfdb9, 0x49cf, + 0x4e37, 0xfa41, 0x26da, 0x92ac, 0xbffd, 0x0b8b, 0xd710, 0x6366, + 0x8db2, 0x39c4, 0xe55f, 0x5129, 0x7c78, 0xc80e, 0x1495, 0xa0e3, + 0xe92c, 0x5d5a, 0x81c1, 0x35b7, 0x18e6, 0xac90, 0x700b, 0xc47d, + 0x2aa9, 0x9edf, 0x4244, 0xf632, 0xdb63, 0x6f15, 0xb38e, 0x07f8, + 0x9c6e, 0x2818, 0xf483, 0x40f5, 0x6da4, 0xd9d2, 0x0549, 0xb13f, + 0x5feb, 0xeb9d, 0x3706, 0x8370, 0xae21, 0x1a57, 0xc6cc, 0x72ba, + 0x3b75, 0x8f03, 0x5398, 0xe7ee, 0xcabf, 0x7ec9, 0xa252, 0x1624, + 0xf8f0, 0x4c86, 0x901d, 0x246b, 0x093a, 0xbd4c, 0x61d7, 0xd5a1, + 0xd259, 0x662f, 0xbab4, 0x0ec2, 0x2393, 0x97e5, 0x4b7e, 0xff08, + 0x11dc, 0xa5aa, 0x7931, 0xcd47, 0xe016, 0x5460, 0x88fb, 0x3c8d, + 0x7542, 0xc134, 0x1daf, 0xa9d9, 0x8488, 0x30fe, 0xec65, 0x5813, + 0xb6c7, 0x02b1, 0xde2a, 0x6a5c, 0x470d, 0xf37b, 0x2fe0, 0x9b96, + 0x38dd, 0x8cab, 0x5030, 0xe446, 0xc917, 0x7d61, 0xa1fa, 0x158c, + 0xfb58, 0x4f2e, 0x93b5, 0x27c3, 0x0a92, 0xbee4, 0x627f, 0xd609, + 0x9fc6, 0x2bb0, 0xf72b, 0x435d, 0x6e0c, 0xda7a, 0x06e1, 0xb297, + 0x5c43, 0xe835, 0x34ae, 0x80d8, 0xad89, 0x19ff, 0xc564, 0x7112, + 0x76ea, 0xc29c, 0x1e07, 0xaa71, 0x8720, 0x3356, 0xefcd, 0x5bbb, + 0xb56f, 0x0119, 0xdd82, 0x69f4, 0x44a5, 0xf0d3, 0x2c48, 0x983e, + 0xd1f1, 0x6587, 0xb91c, 0x0d6a, 0x203b, 0x944d, 0x48d6, 0xfca0, + 0x1274, 0xa602, 0x7a99, 0xceef, 0xe3be, 0x57c8, 0x8b53, 0x3f25, + 0xa4b3, 0x10c5, 0xcc5e, 0x7828, 0x5579, 0xe10f, 0x3d94, 0x89e2, + 0x6736, 0xd340, 0x0fdb, 0xbbad, 0x96fc, 0x228a, 0xfe11, 0x4a67, + 0x03a8, 0xb7de, 0x6b45, 0xdf33, 0xf262, 0x4614, 0x9a8f, 0x2ef9, + 0xc02d, 0x745b, 0xa8c0, 0x1cb6, 0x31e7, 0x8591, 0x590a, 0xed7c, + 0xea84, 0x5ef2, 0x8269, 0x361f, 0x1b4e, 0xaf38, 0x73a3, 0xc7d5, + 0x2901, 0x9d77, 0x41ec, 0xf59a, 0xd8cb, 0x6cbd, 0xb026, 0x0450, + 0x4d9f, 0xf9e9, 0x2572, 0x9104, 0xbc55, 0x0823, 0xd4b8, 0x60ce, + 0x8e1a, 0x3a6c, 0xe6f7, 0x5281, 0x7fd0, 0xcba6, 0x173d, 0xa34b +}; + +const uint16_t crc_table_mcrf4xx[1024] PROGMEM = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78, + 0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08, + 0xcec0, 0xd718, 0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8, + 0x9591, 0x8c49, 0xa621, 0xbff9, 0xf2f1, 0xeb29, 0xc141, 0xd899, + 0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9, 0x0f81, 0x1659, + 0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b, + 0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb, + 0xb6a2, 0xaf7a, 0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa, + 0x7862, 0x61ba, 0x4bd2, 0x520a, 0x1f02, 0x06da, 0x2cb2, 0x356a, + 0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de, 0x12b6, 0x0b6e, + 0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae, + 0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff, + 0x1d37, 0x04ef, 0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f, + 0x6555, 0x7c8d, 0x56e5, 0x4f3d, 0x0235, 0x1bed, 0x3185, 0x285d, + 0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d, 0xff45, 0xe69d, + 0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc, + 0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c, + 0x8ccc, 0x9514, 0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4, + 0x420c, 0x5bd4, 0x71bc, 0x6864, 0x256c, 0x3cb4, 0x16dc, 0x0f04, + 0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5, 0x4d8d, 0x5455, + 0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95, + 0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7, + 0x613f, 0x78e7, 0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37, + 0x3a6e, 0x23b6, 0x09de, 0x1006, 0x5d0e, 0x44d6, 0x6ebe, 0x7766, + 0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16, 0xa07e, 0xb9a6, + 0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2, + 0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962, + 0x5f3b, 0x46e3, 0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233, + 0x91fb, 0x8823, 0xa24b, 0xbb93, 0xf69b, 0xef43, 0xc52b, 0xdcf3, + 0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721, 0xbd49, 0xa491, + 0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51, + 0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100, + 0xb2c8, 0xab10, 0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0, + 0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05, + 0xc6c2, 0x9c1e, 0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7, + 0x8595, 0xdf49, 0x302d, 0x6af1, 0xe6f4, 0xbc28, 0x534c, 0x0990, + 0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea, 0x958e, 0xcf52, + 0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e, + 0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc, + 0x86ae, 0xdc72, 0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab, + 0x406c, 0x1ab0, 0xf5d4, 0xaf08, 0x230d, 0x79d1, 0x96b5, 0xcc69, + 0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb, 0xd0af, 0x8a73, + 0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1, + 0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6, + 0x4521, 0x1ffd, 0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924, + 0x054d, 0x5f91, 0xb0f5, 0xea29, 0x662c, 0x3cf0, 0xd394, 0x8948, + 0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32, 0x1556, 0x4f8a, + 0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd, + 0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f, + 0x0cec, 0x5630, 0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9, + 0xca2e, 0x90f2, 0x7f96, 0x254a, 0xa94f, 0xf393, 0x1cf7, 0x462b, + 0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4, 0x5fa0, 0x057c, + 0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be, + 0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2, + 0xc915, 0x93c9, 0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510, + 0x8a42, 0xd09e, 0x3ffa, 0x6526, 0xe923, 0xb3ff, 0x5c9b, 0x0647, + 0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d, 0x9a59, 0xc085, + 0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f, + 0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d, + 0x8f0f, 0xd5d3, 0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a, + 0x49cd, 0x1311, 0xfc75, 0xa6a9, 0x2aac, 0x7070, 0x9f14, 0xc5c8, + 0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c, 0xdf78, 0x85a4, + 0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366, + 0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031, + 0x4af6, 0x102a, 0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3, + 0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721, + 0xe5d8, 0xf963, 0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9, + 0xc3a1, 0xdf1a, 0xfad7, 0xe66c, 0xb14d, 0xadf6, 0x883b, 0x9480, + 0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e, 0x6de3, 0x7158, + 0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872, + 0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa, + 0x4cf2, 0x5049, 0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3, + 0xa92a, 0xb591, 0x905c, 0x8ce7, 0xdbc6, 0xc77d, 0xe2b0, 0xfe0b, + 0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0, 0x5d2d, 0x4196, + 0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e, + 0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237, + 0x30ce, 0x2c75, 0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef, + 0x99e4, 0x855f, 0xa092, 0xbc29, 0xeb08, 0xf7b3, 0xd27e, 0xcec5, + 0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b, 0x37a6, 0x2b1d, + 0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64, + 0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc, + 0x2d6e, 0x31d5, 0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f, + 0xc8b6, 0xd40d, 0xf1c0, 0xed7b, 0xba5a, 0xa6e1, 0x832c, 0x9f97, + 0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098, 0xa555, 0xb9ee, + 0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36, + 0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c, + 0x47e5, 0x5b5e, 0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4, + 0x619c, 0x7d27, 0x58ea, 0x4451, 0x1370, 0x0fcb, 0x2a06, 0x36bd, + 0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13, 0xcfde, 0xd365, + 0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8, + 0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920, + 0xf878, 0xe4c3, 0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59, + 0x1da0, 0x011b, 0x24d6, 0x386d, 0x6f4c, 0x73f7, 0x563a, 0x4a81, + 0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd, 0xff10, 0xe3ab, + 0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673, + 0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a, + 0x92f3, 0x8e48, 0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2 +}; + +const uint16_t crc_table_modbus[1024] PROGMEM = { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, + 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, + 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, + 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, + 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, + 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, + 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, + 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, + 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, + 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, + 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, + 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, + 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, + 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, + 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, + 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, + 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040, + 0x0000, 0x9001, 0x6001, 0xf000, 0xc002, 0x5003, 0xa003, 0x3002, + 0xc007, 0x5006, 0xa006, 0x3007, 0x0005, 0x9004, 0x6004, 0xf005, + 0xc00d, 0x500c, 0xa00c, 0x300d, 0x000f, 0x900e, 0x600e, 0xf00f, + 0x000a, 0x900b, 0x600b, 0xf00a, 0xc008, 0x5009, 0xa009, 0x3008, + 0xc019, 0x5018, 0xa018, 0x3019, 0x001b, 0x901a, 0x601a, 0xf01b, + 0x001e, 0x901f, 0x601f, 0xf01e, 0xc01c, 0x501d, 0xa01d, 0x301c, + 0x0014, 0x9015, 0x6015, 0xf014, 0xc016, 0x5017, 0xa017, 0x3016, + 0xc013, 0x5012, 0xa012, 0x3013, 0x0011, 0x9010, 0x6010, 0xf011, + 0xc031, 0x5030, 0xa030, 0x3031, 0x0033, 0x9032, 0x6032, 0xf033, + 0x0036, 0x9037, 0x6037, 0xf036, 0xc034, 0x5035, 0xa035, 0x3034, + 0x003c, 0x903d, 0x603d, 0xf03c, 0xc03e, 0x503f, 0xa03f, 0x303e, + 0xc03b, 0x503a, 0xa03a, 0x303b, 0x0039, 0x9038, 0x6038, 0xf039, + 0x0028, 0x9029, 0x6029, 0xf028, 0xc02a, 0x502b, 0xa02b, 0x302a, + 0xc02f, 0x502e, 0xa02e, 0x302f, 0x002d, 0x902c, 0x602c, 0xf02d, + 0xc025, 0x5024, 0xa024, 0x3025, 0x0027, 0x9026, 0x6026, 0xf027, + 0x0022, 0x9023, 0x6023, 0xf022, 0xc020, 0x5021, 0xa021, 0x3020, + 0xc061, 0x5060, 0xa060, 0x3061, 0x0063, 0x9062, 0x6062, 0xf063, + 0x0066, 0x9067, 0x6067, 0xf066, 0xc064, 0x5065, 0xa065, 0x3064, + 0x006c, 0x906d, 0x606d, 0xf06c, 0xc06e, 0x506f, 0xa06f, 0x306e, + 0xc06b, 0x506a, 0xa06a, 0x306b, 0x0069, 0x9068, 0x6068, 0xf069, + 0x0078, 0x9079, 0x6079, 0xf078, 0xc07a, 0x507b, 0xa07b, 0x307a, + 0xc07f, 0x507e, 0xa07e, 0x307f, 0x007d, 0x907c, 0x607c, 0xf07d, + 0xc075, 0x5074, 0xa074, 0x3075, 0x0077, 0x9076, 0x6076, 0xf077, + 0x0072, 0x9073, 0x6073, 0xf072, 0xc070, 0x5071, 0xa071, 0x3070, + 0x0050, 0x9051, 0x6051, 0xf050, 0xc052, 0x5053, 0xa053, 0x3052, + 0xc057, 0x5056, 0xa056, 0x3057, 0x0055, 0x9054, 0x6054, 0xf055, + 0xc05d, 0x505c, 0xa05c, 0x305d, 0x005f, 0x905e, 0x605e, 0xf05f, + 0x005a, 0x905b, 0x605b, 0xf05a, 0xc058, 0x5059, 0xa059, 0x3058, + 0xc049, 0x5048, 0xa048, 0x3049, 0x004b, 0x904a, 0x604a, 0xf04b, + 0x004e, 0x904f, 0x604f, 0xf04e, 0xc04c, 0x504d, 0xa04d, 0x304c, + 0x0044, 0x9045, 0x6045, 0xf044, 0xc046, 0x5047, 0xa047, 0x3046, + 0xc043, 0x5042, 0xa042, 0x3043, 0x0041, 0x9040, 0x6040, 0xf041, + 0x0000, 0xc051, 0xc0a1, 0x00f0, 0xc141, 0x0110, 0x01e0, 0xc1b1, + 0xc281, 0x02d0, 0x0220, 0xc271, 0x03c0, 0xc391, 0xc361, 0x0330, + 0xc501, 0x0550, 0x05a0, 0xc5f1, 0x0440, 0xc411, 0xc4e1, 0x04b0, + 0x0780, 0xc7d1, 0xc721, 0x0770, 0xc6c1, 0x0690, 0x0660, 0xc631, + 0xca01, 0x0a50, 0x0aa0, 0xcaf1, 0x0b40, 0xcb11, 0xcbe1, 0x0bb0, + 0x0880, 0xc8d1, 0xc821, 0x0870, 0xc9c1, 0x0990, 0x0960, 0xc931, + 0x0f00, 0xcf51, 0xcfa1, 0x0ff0, 0xce41, 0x0e10, 0x0ee0, 0xceb1, + 0xcd81, 0x0dd0, 0x0d20, 0xcd71, 0x0cc0, 0xcc91, 0xcc61, 0x0c30, + 0xd401, 0x1450, 0x14a0, 0xd4f1, 0x1540, 0xd511, 0xd5e1, 0x15b0, + 0x1680, 0xd6d1, 0xd621, 0x1670, 0xd7c1, 0x1790, 0x1760, 0xd731, + 0x1100, 0xd151, 0xd1a1, 0x11f0, 0xd041, 0x1010, 0x10e0, 0xd0b1, + 0xd381, 0x13d0, 0x1320, 0xd371, 0x12c0, 0xd291, 0xd261, 0x1230, + 0x1e00, 0xde51, 0xdea1, 0x1ef0, 0xdf41, 0x1f10, 0x1fe0, 0xdfb1, + 0xdc81, 0x1cd0, 0x1c20, 0xdc71, 0x1dc0, 0xdd91, 0xdd61, 0x1d30, + 0xdb01, 0x1b50, 0x1ba0, 0xdbf1, 0x1a40, 0xda11, 0xdae1, 0x1ab0, + 0x1980, 0xd9d1, 0xd921, 0x1970, 0xd8c1, 0x1890, 0x1860, 0xd831, + 0xe801, 0x2850, 0x28a0, 0xe8f1, 0x2940, 0xe911, 0xe9e1, 0x29b0, + 0x2a80, 0xead1, 0xea21, 0x2a70, 0xebc1, 0x2b90, 0x2b60, 0xeb31, + 0x2d00, 0xed51, 0xeda1, 0x2df0, 0xec41, 0x2c10, 0x2ce0, 0xecb1, + 0xef81, 0x2fd0, 0x2f20, 0xef71, 0x2ec0, 0xee91, 0xee61, 0x2e30, + 0x2200, 0xe251, 0xe2a1, 0x22f0, 0xe341, 0x2310, 0x23e0, 0xe3b1, + 0xe081, 0x20d0, 0x2020, 0xe071, 0x21c0, 0xe191, 0xe161, 0x2130, + 0xe701, 0x2750, 0x27a0, 0xe7f1, 0x2640, 0xe611, 0xe6e1, 0x26b0, + 0x2580, 0xe5d1, 0xe521, 0x2570, 0xe4c1, 0x2490, 0x2460, 0xe431, + 0x3c00, 0xfc51, 0xfca1, 0x3cf0, 0xfd41, 0x3d10, 0x3de0, 0xfdb1, + 0xfe81, 0x3ed0, 0x3e20, 0xfe71, 0x3fc0, 0xff91, 0xff61, 0x3f30, + 0xf901, 0x3950, 0x39a0, 0xf9f1, 0x3840, 0xf811, 0xf8e1, 0x38b0, + 0x3b80, 0xfbd1, 0xfb21, 0x3b70, 0xfac1, 0x3a90, 0x3a60, 0xfa31, + 0xf601, 0x3650, 0x36a0, 0xf6f1, 0x3740, 0xf711, 0xf7e1, 0x37b0, + 0x3480, 0xf4d1, 0xf421, 0x3470, 0xf5c1, 0x3590, 0x3560, 0xf531, + 0x3300, 0xf351, 0xf3a1, 0x33f0, 0xf241, 0x3210, 0x32e0, 0xf2b1, + 0xf181, 0x31d0, 0x3120, 0xf171, 0x30c0, 0xf091, 0xf061, 0x3030, + 0x0000, 0xfc01, 0xb801, 0x4400, 0x3001, 0xcc00, 0x8800, 0x7401, + 0x6002, 0x9c03, 0xd803, 0x2402, 0x5003, 0xac02, 0xe802, 0x1403, + 0xc004, 0x3c05, 0x7805, 0x8404, 0xf005, 0x0c04, 0x4804, 0xb405, + 0xa006, 0x5c07, 0x1807, 0xe406, 0x9007, 0x6c06, 0x2806, 0xd407, + 0xc00b, 0x3c0a, 0x780a, 0x840b, 0xf00a, 0x0c0b, 0x480b, 0xb40a, + 0xa009, 0x5c08, 0x1808, 0xe409, 0x9008, 0x6c09, 0x2809, 0xd408, + 0x000f, 0xfc0e, 0xb80e, 0x440f, 0x300e, 0xcc0f, 0x880f, 0x740e, + 0x600d, 0x9c0c, 0xd80c, 0x240d, 0x500c, 0xac0d, 0xe80d, 0x140c, + 0xc015, 0x3c14, 0x7814, 0x8415, 0xf014, 0x0c15, 0x4815, 0xb414, + 0xa017, 0x5c16, 0x1816, 0xe417, 0x9016, 0x6c17, 0x2817, 0xd416, + 0x0011, 0xfc10, 0xb810, 0x4411, 0x3010, 0xcc11, 0x8811, 0x7410, + 0x6013, 0x9c12, 0xd812, 0x2413, 0x5012, 0xac13, 0xe813, 0x1412, + 0x001e, 0xfc1f, 0xb81f, 0x441e, 0x301f, 0xcc1e, 0x881e, 0x741f, + 0x601c, 0x9c1d, 0xd81d, 0x241c, 0x501d, 0xac1c, 0xe81c, 0x141d, + 0xc01a, 0x3c1b, 0x781b, 0x841a, 0xf01b, 0x0c1a, 0x481a, 0xb41b, + 0xa018, 0x5c19, 0x1819, 0xe418, 0x9019, 0x6c18, 0x2818, 0xd419, + 0xc029, 0x3c28, 0x7828, 0x8429, 0xf028, 0x0c29, 0x4829, 0xb428, + 0xa02b, 0x5c2a, 0x182a, 0xe42b, 0x902a, 0x6c2b, 0x282b, 0xd42a, + 0x002d, 0xfc2c, 0xb82c, 0x442d, 0x302c, 0xcc2d, 0x882d, 0x742c, + 0x602f, 0x9c2e, 0xd82e, 0x242f, 0x502e, 0xac2f, 0xe82f, 0x142e, + 0x0022, 0xfc23, 0xb823, 0x4422, 0x3023, 0xcc22, 0x8822, 0x7423, + 0x6020, 0x9c21, 0xd821, 0x2420, 0x5021, 0xac20, 0xe820, 0x1421, + 0xc026, 0x3c27, 0x7827, 0x8426, 0xf027, 0x0c26, 0x4826, 0xb427, + 0xa024, 0x5c25, 0x1825, 0xe424, 0x9025, 0x6c24, 0x2824, 0xd425, + 0x003c, 0xfc3d, 0xb83d, 0x443c, 0x303d, 0xcc3c, 0x883c, 0x743d, + 0x603e, 0x9c3f, 0xd83f, 0x243e, 0x503f, 0xac3e, 0xe83e, 0x143f, + 0xc038, 0x3c39, 0x7839, 0x8438, 0xf039, 0x0c38, 0x4838, 0xb439, + 0xa03a, 0x5c3b, 0x183b, 0xe43a, 0x903b, 0x6c3a, 0x283a, 0xd43b, + 0xc037, 0x3c36, 0x7836, 0x8437, 0xf036, 0x0c37, 0x4837, 0xb436, + 0xa035, 0x5c34, 0x1834, 0xe435, 0x9034, 0x6c35, 0x2835, 0xd434, + 0x0033, 0xfc32, 0xb832, 0x4433, 0x3032, 0xcc33, 0x8833, 0x7432, + 0x6031, 0x9c30, 0xd830, 0x2431, 0x5030, 0xac31, 0xe831, 0x1430 +}; + +const uint16_t crc_table_kermit[1024] PROGMEM = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78, + 0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08, + 0xcec0, 0xd718, 0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8, + 0x9591, 0x8c49, 0xa621, 0xbff9, 0xf2f1, 0xeb29, 0xc141, 0xd899, + 0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9, 0x0f81, 0x1659, + 0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b, + 0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb, + 0xb6a2, 0xaf7a, 0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa, + 0x7862, 0x61ba, 0x4bd2, 0x520a, 0x1f02, 0x06da, 0x2cb2, 0x356a, + 0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de, 0x12b6, 0x0b6e, + 0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae, + 0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff, + 0x1d37, 0x04ef, 0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f, + 0x6555, 0x7c8d, 0x56e5, 0x4f3d, 0x0235, 0x1bed, 0x3185, 0x285d, + 0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d, 0xff45, 0xe69d, + 0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc, + 0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c, + 0x8ccc, 0x9514, 0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4, + 0x420c, 0x5bd4, 0x71bc, 0x6864, 0x256c, 0x3cb4, 0x16dc, 0x0f04, + 0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5, 0x4d8d, 0x5455, + 0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95, + 0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7, + 0x613f, 0x78e7, 0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37, + 0x3a6e, 0x23b6, 0x09de, 0x1006, 0x5d0e, 0x44d6, 0x6ebe, 0x7766, + 0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16, 0xa07e, 0xb9a6, + 0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2, + 0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962, + 0x5f3b, 0x46e3, 0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233, + 0x91fb, 0x8823, 0xa24b, 0xbb93, 0xf69b, 0xef43, 0xc52b, 0xdcf3, + 0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721, 0xbd49, 0xa491, + 0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51, + 0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100, + 0xb2c8, 0xab10, 0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0, + 0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05, + 0xc6c2, 0x9c1e, 0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7, + 0x8595, 0xdf49, 0x302d, 0x6af1, 0xe6f4, 0xbc28, 0x534c, 0x0990, + 0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea, 0x958e, 0xcf52, + 0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e, + 0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc, + 0x86ae, 0xdc72, 0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab, + 0x406c, 0x1ab0, 0xf5d4, 0xaf08, 0x230d, 0x79d1, 0x96b5, 0xcc69, + 0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb, 0xd0af, 0x8a73, + 0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1, + 0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6, + 0x4521, 0x1ffd, 0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924, + 0x054d, 0x5f91, 0xb0f5, 0xea29, 0x662c, 0x3cf0, 0xd394, 0x8948, + 0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32, 0x1556, 0x4f8a, + 0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd, + 0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f, + 0x0cec, 0x5630, 0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9, + 0xca2e, 0x90f2, 0x7f96, 0x254a, 0xa94f, 0xf393, 0x1cf7, 0x462b, + 0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4, 0x5fa0, 0x057c, + 0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be, + 0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2, + 0xc915, 0x93c9, 0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510, + 0x8a42, 0xd09e, 0x3ffa, 0x6526, 0xe923, 0xb3ff, 0x5c9b, 0x0647, + 0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d, 0x9a59, 0xc085, + 0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f, + 0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d, + 0x8f0f, 0xd5d3, 0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a, + 0x49cd, 0x1311, 0xfc75, 0xa6a9, 0x2aac, 0x7070, 0x9f14, 0xc5c8, + 0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c, 0xdf78, 0x85a4, + 0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366, + 0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031, + 0x4af6, 0x102a, 0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3, + 0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721, + 0xe5d8, 0xf963, 0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9, + 0xc3a1, 0xdf1a, 0xfad7, 0xe66c, 0xb14d, 0xadf6, 0x883b, 0x9480, + 0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e, 0x6de3, 0x7158, + 0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872, + 0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa, + 0x4cf2, 0x5049, 0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3, + 0xa92a, 0xb591, 0x905c, 0x8ce7, 0xdbc6, 0xc77d, 0xe2b0, 0xfe0b, + 0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0, 0x5d2d, 0x4196, + 0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e, + 0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237, + 0x30ce, 0x2c75, 0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef, + 0x99e4, 0x855f, 0xa092, 0xbc29, 0xeb08, 0xf7b3, 0xd27e, 0xcec5, + 0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b, 0x37a6, 0x2b1d, + 0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64, + 0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc, + 0x2d6e, 0x31d5, 0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f, + 0xc8b6, 0xd40d, 0xf1c0, 0xed7b, 0xba5a, 0xa6e1, 0x832c, 0x9f97, + 0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098, 0xa555, 0xb9ee, + 0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36, + 0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c, + 0x47e5, 0x5b5e, 0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4, + 0x619c, 0x7d27, 0x58ea, 0x4451, 0x1370, 0x0fcb, 0x2a06, 0x36bd, + 0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13, 0xcfde, 0xd365, + 0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8, + 0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920, + 0xf878, 0xe4c3, 0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59, + 0x1da0, 0x011b, 0x24d6, 0x386d, 0x6f4c, 0x73f7, 0x563a, 0x4a81, + 0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd, 0xff10, 0xe3ab, + 0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673, + 0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a, + 0x92f3, 0x8e48, 0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2 +}; + +const uint16_t crc_table_xmodem[1024] PROGMEM = { + 0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xa550, 0xc660, 0xe770, + 0x0881, 0x2991, 0x4aa1, 0x6bb1, 0x8cc1, 0xadd1, 0xcee1, 0xeff1, + 0x3112, 0x1002, 0x7332, 0x5222, 0xb552, 0x9442, 0xf772, 0xd662, + 0x3993, 0x1883, 0x7bb3, 0x5aa3, 0xbdd3, 0x9cc3, 0xfff3, 0xdee3, + 0x6224, 0x4334, 0x2004, 0x0114, 0xe664, 0xc774, 0xa444, 0x8554, + 0x6aa5, 0x4bb5, 0x2885, 0x0995, 0xeee5, 0xcff5, 0xacc5, 0x8dd5, + 0x5336, 0x7226, 0x1116, 0x3006, 0xd776, 0xf666, 0x9556, 0xb446, + 0x5bb7, 0x7aa7, 0x1997, 0x3887, 0xdff7, 0xfee7, 0x9dd7, 0xbcc7, + 0xc448, 0xe558, 0x8668, 0xa778, 0x4008, 0x6118, 0x0228, 0x2338, + 0xccc9, 0xedd9, 0x8ee9, 0xaff9, 0x4889, 0x6999, 0x0aa9, 0x2bb9, + 0xf55a, 0xd44a, 0xb77a, 0x966a, 0x711a, 0x500a, 0x333a, 0x122a, + 0xfddb, 0xdccb, 0xbffb, 0x9eeb, 0x799b, 0x588b, 0x3bbb, 0x1aab, + 0xa66c, 0x877c, 0xe44c, 0xc55c, 0x222c, 0x033c, 0x600c, 0x411c, + 0xaeed, 0x8ffd, 0xeccd, 0xcddd, 0x2aad, 0x0bbd, 0x688d, 0x499d, + 0x977e, 0xb66e, 0xd55e, 0xf44e, 0x133e, 0x322e, 0x511e, 0x700e, + 0x9fff, 0xbeef, 0xdddf, 0xfccf, 0x1bbf, 0x3aaf, 0x599f, 0x788f, + 0x8891, 0xa981, 0xcab1, 0xeba1, 0x0cd1, 0x2dc1, 0x4ef1, 0x6fe1, + 0x8010, 0xa100, 0xc230, 0xe320, 0x0450, 0x2540, 0x4670, 0x6760, + 0xb983, 0x9893, 0xfba3, 0xdab3, 0x3dc3, 0x1cd3, 0x7fe3, 0x5ef3, + 0xb102, 0x9012, 0xf322, 0xd232, 0x3542, 0x1452, 0x7762, 0x5672, + 0xeab5, 0xcba5, 0xa895, 0x8985, 0x6ef5, 0x4fe5, 0x2cd5, 0x0dc5, + 0xe234, 0xc324, 0xa014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544, + 0xdba7, 0xfab7, 0x9987, 0xb897, 0x5fe7, 0x7ef7, 0x1dc7, 0x3cd7, + 0xd326, 0xf236, 0x9106, 0xb016, 0x5766, 0x7676, 0x1546, 0x3456, + 0x4cd9, 0x6dc9, 0x0ef9, 0x2fe9, 0xc899, 0xe989, 0x8ab9, 0xaba9, + 0x4458, 0x6548, 0x0678, 0x2768, 0xc018, 0xe108, 0x8238, 0xa328, + 0x7dcb, 0x5cdb, 0x3feb, 0x1efb, 0xf98b, 0xd89b, 0xbbab, 0x9abb, + 0x754a, 0x545a, 0x376a, 0x167a, 0xf10a, 0xd01a, 0xb32a, 0x923a, + 0x2efd, 0x0fed, 0x6cdd, 0x4dcd, 0xaabd, 0x8bad, 0xe89d, 0xc98d, + 0x267c, 0x076c, 0x645c, 0x454c, 0xa23c, 0x832c, 0xe01c, 0xc10c, + 0x1fef, 0x3eff, 0x5dcf, 0x7cdf, 0x9baf, 0xbabf, 0xd98f, 0xf89f, + 0x176e, 0x367e, 0x554e, 0x745e, 0x932e, 0xb23e, 0xd10e, 0xf01e, + 0x0000, 0x3133, 0x6266, 0x5355, 0xc4cc, 0xf5ff, 0xa6aa, 0x9799, + 0xa989, 0x98ba, 0xcbef, 0xfadc, 0x6d45, 0x5c76, 0x0f23, 0x3e10, + 0x7303, 0x4230, 0x1165, 0x2056, 0xb7cf, 0x86fc, 0xd5a9, 0xe49a, + 0xda8a, 0xebb9, 0xb8ec, 0x89df, 0x1e46, 0x2f75, 0x7c20, 0x4d13, + 0xe606, 0xd735, 0x8460, 0xb553, 0x22ca, 0x13f9, 0x40ac, 0x719f, + 0x4f8f, 0x7ebc, 0x2de9, 0x1cda, 0x8b43, 0xba70, 0xe925, 0xd816, + 0x9505, 0xa436, 0xf763, 0xc650, 0x51c9, 0x60fa, 0x33af, 0x029c, + 0x3c8c, 0x0dbf, 0x5eea, 0x6fd9, 0xf840, 0xc973, 0x9a26, 0xab15, + 0xcc0d, 0xfd3e, 0xae6b, 0x9f58, 0x08c1, 0x39f2, 0x6aa7, 0x5b94, + 0x6584, 0x54b7, 0x07e2, 0x36d1, 0xa148, 0x907b, 0xc32e, 0xf21d, + 0xbf0e, 0x8e3d, 0xdd68, 0xec5b, 0x7bc2, 0x4af1, 0x19a4, 0x2897, + 0x1687, 0x27b4, 0x74e1, 0x45d2, 0xd24b, 0xe378, 0xb02d, 0x811e, + 0x2a0b, 0x1b38, 0x486d, 0x795e, 0xeec7, 0xdff4, 0x8ca1, 0xbd92, + 0x8382, 0xb2b1, 0xe1e4, 0xd0d7, 0x474e, 0x767d, 0x2528, 0x141b, + 0x5908, 0x683b, 0x3b6e, 0x0a5d, 0x9dc4, 0xacf7, 0xffa2, 0xce91, + 0xf081, 0xc1b2, 0x92e7, 0xa3d4, 0x344d, 0x057e, 0x562b, 0x6718, + 0x981b, 0xa928, 0xfa7d, 0xcb4e, 0x5cd7, 0x6de4, 0x3eb1, 0x0f82, + 0x3192, 0x00a1, 0x53f4, 0x62c7, 0xf55e, 0xc46d, 0x9738, 0xa60b, + 0xeb18, 0xda2b, 0x897e, 0xb84d, 0x2fd4, 0x1ee7, 0x4db2, 0x7c81, + 0x4291, 0x73a2, 0x20f7, 0x11c4, 0x865d, 0xb76e, 0xe43b, 0xd508, + 0x7e1d, 0x4f2e, 0x1c7b, 0x2d48, 0xbad1, 0x8be2, 0xd8b7, 0xe984, + 0xd794, 0xe6a7, 0xb5f2, 0x84c1, 0x1358, 0x226b, 0x713e, 0x400d, + 0x0d1e, 0x3c2d, 0x6f78, 0x5e4b, 0xc9d2, 0xf8e1, 0xabb4, 0x9a87, + 0xa497, 0x95a4, 0xc6f1, 0xf7c2, 0x605b, 0x5168, 0x023d, 0x330e, + 0x5416, 0x6525, 0x3670, 0x0743, 0x90da, 0xa1e9, 0xf2bc, 0xc38f, + 0xfd9f, 0xccac, 0x9ff9, 0xaeca, 0x3953, 0x0860, 0x5b35, 0x6a06, + 0x2715, 0x1626, 0x4573, 0x7440, 0xe3d9, 0xd2ea, 0x81bf, 0xb08c, + 0x8e9c, 0xbfaf, 0xecfa, 0xddc9, 0x4a50, 0x7b63, 0x2836, 0x1905, + 0xb210, 0x8323, 0xd076, 0xe145, 0x76dc, 0x47ef, 0x14ba, 0x2589, + 0x1b99, 0x2aaa, 0x79ff, 0x48cc, 0xdf55, 0xee66, 0xbd33, 0x8c00, + 0xc113, 0xf020, 0xa375, 0x9246, 0x05df, 0x34ec, 0x67b9, 0x568a, + 0x689a, 0x59a9, 0x0afc, 0x3bcf, 0xac56, 0x9d65, 0xce30, 0xff03, + 0x0000, 0x3037, 0x606e, 0x5059, 0xc0dc, 0xf0eb, 0xa0b2, 0x9085, + 0xa1a9, 0x919e, 0xc1c7, 0xf1f0, 0x6175, 0x5142, 0x011b, 0x312c, + 0x6343, 0x5374, 0x032d, 0x331a, 0xa39f, 0x93a8, 0xc3f1, 0xf3c6, + 0xc2ea, 0xf2dd, 0xa284, 0x92b3, 0x0236, 0x3201, 0x6258, 0x526f, + 0xc686, 0xf6b1, 0xa6e8, 0x96df, 0x065a, 0x366d, 0x6634, 0x5603, + 0x672f, 0x5718, 0x0741, 0x3776, 0xa7f3, 0x97c4, 0xc79d, 0xf7aa, + 0xa5c5, 0x95f2, 0xc5ab, 0xf59c, 0x6519, 0x552e, 0x0577, 0x3540, + 0x046c, 0x345b, 0x6402, 0x5435, 0xc4b0, 0xf487, 0xa4de, 0x94e9, + 0xad1d, 0x9d2a, 0xcd73, 0xfd44, 0x6dc1, 0x5df6, 0x0daf, 0x3d98, + 0x0cb4, 0x3c83, 0x6cda, 0x5ced, 0xcc68, 0xfc5f, 0xac06, 0x9c31, + 0xce5e, 0xfe69, 0xae30, 0x9e07, 0x0e82, 0x3eb5, 0x6eec, 0x5edb, + 0x6ff7, 0x5fc0, 0x0f99, 0x3fae, 0xaf2b, 0x9f1c, 0xcf45, 0xff72, + 0x6b9b, 0x5bac, 0x0bf5, 0x3bc2, 0xab47, 0x9b70, 0xcb29, 0xfb1e, + 0xca32, 0xfa05, 0xaa5c, 0x9a6b, 0x0aee, 0x3ad9, 0x6a80, 0x5ab7, + 0x08d8, 0x38ef, 0x68b6, 0x5881, 0xc804, 0xf833, 0xa86a, 0x985d, + 0xa971, 0x9946, 0xc91f, 0xf928, 0x69ad, 0x599a, 0x09c3, 0x39f4, + 0x5a3b, 0x6a0c, 0x3a55, 0x0a62, 0x9ae7, 0xaad0, 0xfa89, 0xcabe, + 0xfb92, 0xcba5, 0x9bfc, 0xabcb, 0x3b4e, 0x0b79, 0x5b20, 0x6b17, + 0x3978, 0x094f, 0x5916, 0x6921, 0xf9a4, 0xc993, 0x99ca, 0xa9fd, + 0x98d1, 0xa8e6, 0xf8bf, 0xc888, 0x580d, 0x683a, 0x3863, 0x0854, + 0x9cbd, 0xac8a, 0xfcd3, 0xcce4, 0x5c61, 0x6c56, 0x3c0f, 0x0c38, + 0x3d14, 0x0d23, 0x5d7a, 0x6d4d, 0xfdc8, 0xcdff, 0x9da6, 0xad91, + 0xfffe, 0xcfc9, 0x9f90, 0xafa7, 0x3f22, 0x0f15, 0x5f4c, 0x6f7b, + 0x5e57, 0x6e60, 0x3e39, 0x0e0e, 0x9e8b, 0xaebc, 0xfee5, 0xced2, + 0xf726, 0xc711, 0x9748, 0xa77f, 0x37fa, 0x07cd, 0x5794, 0x67a3, + 0x568f, 0x66b8, 0x36e1, 0x06d6, 0x9653, 0xa664, 0xf63d, 0xc60a, + 0x9465, 0xa452, 0xf40b, 0xc43c, 0x54b9, 0x648e, 0x34d7, 0x04e0, + 0x35cc, 0x05fb, 0x55a2, 0x6595, 0xf510, 0xc527, 0x957e, 0xa549, + 0x31a0, 0x0197, 0x51ce, 0x61f9, 0xf17c, 0xc14b, 0x9112, 0xa125, + 0x9009, 0xa03e, 0xf067, 0xc050, 0x50d5, 0x60e2, 0x30bb, 0x008c, + 0x52e3, 0x62d4, 0x328d, 0x02ba, 0x923f, 0xa208, 0xf251, 0xc266, + 0xf34a, 0xc37d, 0x9324, 0xa313, 0x3396, 0x03a1, 0x53f8, 0x63cf, + 0x0000, 0xb476, 0x68ed, 0xdc9b, 0xf1ca, 0x45bc, 0x9927, 0x2d51, + 0xc385, 0x77f3, 0xab68, 0x1f1e, 0x324f, 0x8639, 0x5aa2, 0xeed4, + 0xa71b, 0x136d, 0xcff6, 0x7b80, 0x56d1, 0xe2a7, 0x3e3c, 0x8a4a, + 0x649e, 0xd0e8, 0x0c73, 0xb805, 0x9554, 0x2122, 0xfdb9, 0x49cf, + 0x4e37, 0xfa41, 0x26da, 0x92ac, 0xbffd, 0x0b8b, 0xd710, 0x6366, + 0x8db2, 0x39c4, 0xe55f, 0x5129, 0x7c78, 0xc80e, 0x1495, 0xa0e3, + 0xe92c, 0x5d5a, 0x81c1, 0x35b7, 0x18e6, 0xac90, 0x700b, 0xc47d, + 0x2aa9, 0x9edf, 0x4244, 0xf632, 0xdb63, 0x6f15, 0xb38e, 0x07f8, + 0x9c6e, 0x2818, 0xf483, 0x40f5, 0x6da4, 0xd9d2, 0x0549, 0xb13f, + 0x5feb, 0xeb9d, 0x3706, 0x8370, 0xae21, 0x1a57, 0xc6cc, 0x72ba, + 0x3b75, 0x8f03, 0x5398, 0xe7ee, 0xcabf, 0x7ec9, 0xa252, 0x1624, + 0xf8f0, 0x4c86, 0x901d, 0x246b, 0x093a, 0xbd4c, 0x61d7, 0xd5a1, + 0xd259, 0x662f, 0xbab4, 0x0ec2, 0x2393, 0x97e5, 0x4b7e, 0xff08, + 0x11dc, 0xa5aa, 0x7931, 0xcd47, 0xe016, 0x5460, 0x88fb, 0x3c8d, + 0x7542, 0xc134, 0x1daf, 0xa9d9, 0x8488, 0x30fe, 0xec65, 0x5813, + 0xb6c7, 0x02b1, 0xde2a, 0x6a5c, 0x470d, 0xf37b, 0x2fe0, 0x9b96, + 0x38dd, 0x8cab, 0x5030, 0xe446, 0xc917, 0x7d61, 0xa1fa, 0x158c, + 0xfb58, 0x4f2e, 0x93b5, 0x27c3, 0x0a92, 0xbee4, 0x627f, 0xd609, + 0x9fc6, 0x2bb0, 0xf72b, 0x435d, 0x6e0c, 0xda7a, 0x06e1, 0xb297, + 0x5c43, 0xe835, 0x34ae, 0x80d8, 0xad89, 0x19ff, 0xc564, 0x7112, + 0x76ea, 0xc29c, 0x1e07, 0xaa71, 0x8720, 0x3356, 0xefcd, 0x5bbb, + 0xb56f, 0x0119, 0xdd82, 0x69f4, 0x44a5, 0xf0d3, 0x2c48, 0x983e, + 0xd1f1, 0x6587, 0xb91c, 0x0d6a, 0x203b, 0x944d, 0x48d6, 0xfca0, + 0x1274, 0xa602, 0x7a99, 0xceef, 0xe3be, 0x57c8, 0x8b53, 0x3f25, + 0xa4b3, 0x10c5, 0xcc5e, 0x7828, 0x5579, 0xe10f, 0x3d94, 0x89e2, + 0x6736, 0xd340, 0x0fdb, 0xbbad, 0x96fc, 0x228a, 0xfe11, 0x4a67, + 0x03a8, 0xb7de, 0x6b45, 0xdf33, 0xf262, 0x4614, 0x9a8f, 0x2ef9, + 0xc02d, 0x745b, 0xa8c0, 0x1cb6, 0x31e7, 0x8591, 0x590a, 0xed7c, + 0xea84, 0x5ef2, 0x8269, 0x361f, 0x1b4e, 0xaf38, 0x73a3, 0xc7d5, + 0x2901, 0x9d77, 0x41ec, 0xf59a, 0xd8cb, 0x6cbd, 0xb026, 0x0450, + 0x4d9f, 0xf9e9, 0x2572, 0x9104, 0xbc55, 0x0823, 0xd4b8, 0x60ce, + 0x8e1a, 0x3a6c, 0xe6f7, 0x5281, 0x7fd0, 0xcba6, 0x173d, 0xa34b +}; + +const uint16_t crc_table_x25[1024] PROGMEM = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78, + 0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08, + 0xcec0, 0xd718, 0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8, + 0x9591, 0x8c49, 0xa621, 0xbff9, 0xf2f1, 0xeb29, 0xc141, 0xd899, + 0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9, 0x0f81, 0x1659, + 0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b, + 0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb, + 0xb6a2, 0xaf7a, 0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa, + 0x7862, 0x61ba, 0x4bd2, 0x520a, 0x1f02, 0x06da, 0x2cb2, 0x356a, + 0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de, 0x12b6, 0x0b6e, + 0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae, + 0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff, + 0x1d37, 0x04ef, 0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f, + 0x6555, 0x7c8d, 0x56e5, 0x4f3d, 0x0235, 0x1bed, 0x3185, 0x285d, + 0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d, 0xff45, 0xe69d, + 0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc, + 0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c, + 0x8ccc, 0x9514, 0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4, + 0x420c, 0x5bd4, 0x71bc, 0x6864, 0x256c, 0x3cb4, 0x16dc, 0x0f04, + 0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5, 0x4d8d, 0x5455, + 0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95, + 0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7, + 0x613f, 0x78e7, 0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37, + 0x3a6e, 0x23b6, 0x09de, 0x1006, 0x5d0e, 0x44d6, 0x6ebe, 0x7766, + 0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16, 0xa07e, 0xb9a6, + 0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2, + 0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962, + 0x5f3b, 0x46e3, 0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233, + 0x91fb, 0x8823, 0xa24b, 0xbb93, 0xf69b, 0xef43, 0xc52b, 0xdcf3, + 0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721, 0xbd49, 0xa491, + 0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51, + 0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100, + 0xb2c8, 0xab10, 0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0, + 0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05, + 0xc6c2, 0x9c1e, 0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7, + 0x8595, 0xdf49, 0x302d, 0x6af1, 0xe6f4, 0xbc28, 0x534c, 0x0990, + 0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea, 0x958e, 0xcf52, + 0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e, + 0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc, + 0x86ae, 0xdc72, 0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab, + 0x406c, 0x1ab0, 0xf5d4, 0xaf08, 0x230d, 0x79d1, 0x96b5, 0xcc69, + 0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb, 0xd0af, 0x8a73, + 0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1, + 0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6, + 0x4521, 0x1ffd, 0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924, + 0x054d, 0x5f91, 0xb0f5, 0xea29, 0x662c, 0x3cf0, 0xd394, 0x8948, + 0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32, 0x1556, 0x4f8a, + 0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd, + 0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f, + 0x0cec, 0x5630, 0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9, + 0xca2e, 0x90f2, 0x7f96, 0x254a, 0xa94f, 0xf393, 0x1cf7, 0x462b, + 0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4, 0x5fa0, 0x057c, + 0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be, + 0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2, + 0xc915, 0x93c9, 0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510, + 0x8a42, 0xd09e, 0x3ffa, 0x6526, 0xe923, 0xb3ff, 0x5c9b, 0x0647, + 0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d, 0x9a59, 0xc085, + 0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f, + 0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d, + 0x8f0f, 0xd5d3, 0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a, + 0x49cd, 0x1311, 0xfc75, 0xa6a9, 0x2aac, 0x7070, 0x9f14, 0xc5c8, + 0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c, 0xdf78, 0x85a4, + 0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366, + 0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031, + 0x4af6, 0x102a, 0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3, + 0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721, + 0xe5d8, 0xf963, 0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9, + 0xc3a1, 0xdf1a, 0xfad7, 0xe66c, 0xb14d, 0xadf6, 0x883b, 0x9480, + 0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e, 0x6de3, 0x7158, + 0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872, + 0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa, + 0x4cf2, 0x5049, 0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3, + 0xa92a, 0xb591, 0x905c, 0x8ce7, 0xdbc6, 0xc77d, 0xe2b0, 0xfe0b, + 0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0, 0x5d2d, 0x4196, + 0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e, + 0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237, + 0x30ce, 0x2c75, 0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef, + 0x99e4, 0x855f, 0xa092, 0xbc29, 0xeb08, 0xf7b3, 0xd27e, 0xcec5, + 0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b, 0x37a6, 0x2b1d, + 0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64, + 0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc, + 0x2d6e, 0x31d5, 0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f, + 0xc8b6, 0xd40d, 0xf1c0, 0xed7b, 0xba5a, 0xa6e1, 0x832c, 0x9f97, + 0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098, 0xa555, 0xb9ee, + 0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36, + 0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c, + 0x47e5, 0x5b5e, 0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4, + 0x619c, 0x7d27, 0x58ea, 0x4451, 0x1370, 0x0fcb, 0x2a06, 0x36bd, + 0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13, 0xcfde, 0xd365, + 0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8, + 0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920, + 0xf878, 0xe4c3, 0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59, + 0x1da0, 0x011b, 0x24d6, 0x386d, 0x6f4c, 0x73f7, 0x563a, 0x4a81, + 0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd, 0xff10, 0xe3ab, + 0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673, + 0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a, + 0x92f3, 0x8e48, 0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2 +}; + +const uint32_t crc_table_crc32[256] PROGMEM = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +const uint32_t crc_table_crc32_big[1024] PROGMEM = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, + 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, + 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, + 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, + 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, + 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, + 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, + 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, + 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, + 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, + 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, + 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, + 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, + 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, + 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, + 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, + 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, + 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, + 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, + 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, + 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, + 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, + 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, + 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, + 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, + 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, + 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, + 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, + 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, + 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, + 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, + 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, + 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, + 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, + 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, + 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, + 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, + 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, + 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, + 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, + 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, + 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, + 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, + 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, + 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, + 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, + 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, + 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, + 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, + 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, + 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, + 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, + 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, + 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, + 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, + 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, + 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, + 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, + 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, + 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, + 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, + 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, + 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, + 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, + 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, + 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, + 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, + 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, + 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, + 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, + 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, + 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, + 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, + 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, + 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, + 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, + 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, + 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, + 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, + 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, + 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, + 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, + 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, + 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, + 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, + 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, + 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, + 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, + 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, + 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, + 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, + 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, + 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, + 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, + 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, + 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed, + 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, + 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, + 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, + 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, + 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, + 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, + 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, + 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, + 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, + 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, + 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, + 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, + 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, + 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, + 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, + 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, + 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, + 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, + 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, + 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, + 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, + 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, + 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, + 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, + 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, + 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, + 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, + 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, + 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, + 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, + 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, + 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, + 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, + 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, + 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, + 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, + 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, + 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, + 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, + 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, + 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, + 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, + 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, + 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, + 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, + 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, + 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, + 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 +}; + +const uint32_t crc_table_cksum[256] PROGMEM = { + 0x00000000, 0xb71dc104, 0x6e3b8209, 0xd926430d, + 0xdc760413, 0x6b6bc517, 0xb24d861a, 0x0550471e, + 0xb8ed0826, 0x0ff0c922, 0xd6d68a2f, 0x61cb4b2b, + 0x649b0c35, 0xd386cd31, 0x0aa08e3c, 0xbdbd4f38, + 0x70db114c, 0xc7c6d048, 0x1ee09345, 0xa9fd5241, + 0xacad155f, 0x1bb0d45b, 0xc2969756, 0x758b5652, + 0xc836196a, 0x7f2bd86e, 0xa60d9b63, 0x11105a67, + 0x14401d79, 0xa35ddc7d, 0x7a7b9f70, 0xcd665e74, + 0xe0b62398, 0x57abe29c, 0x8e8da191, 0x39906095, + 0x3cc0278b, 0x8bdde68f, 0x52fba582, 0xe5e66486, + 0x585b2bbe, 0xef46eaba, 0x3660a9b7, 0x817d68b3, + 0x842d2fad, 0x3330eea9, 0xea16ada4, 0x5d0b6ca0, + 0x906d32d4, 0x2770f3d0, 0xfe56b0dd, 0x494b71d9, + 0x4c1b36c7, 0xfb06f7c3, 0x2220b4ce, 0x953d75ca, + 0x28803af2, 0x9f9dfbf6, 0x46bbb8fb, 0xf1a679ff, + 0xf4f63ee1, 0x43ebffe5, 0x9acdbce8, 0x2dd07dec, + 0x77708634, 0xc06d4730, 0x194b043d, 0xae56c539, + 0xab068227, 0x1c1b4323, 0xc53d002e, 0x7220c12a, + 0xcf9d8e12, 0x78804f16, 0xa1a60c1b, 0x16bbcd1f, + 0x13eb8a01, 0xa4f64b05, 0x7dd00808, 0xcacdc90c, + 0x07ab9778, 0xb0b6567c, 0x69901571, 0xde8dd475, + 0xdbdd936b, 0x6cc0526f, 0xb5e61162, 0x02fbd066, + 0xbf469f5e, 0x085b5e5a, 0xd17d1d57, 0x6660dc53, + 0x63309b4d, 0xd42d5a49, 0x0d0b1944, 0xba16d840, + 0x97c6a5ac, 0x20db64a8, 0xf9fd27a5, 0x4ee0e6a1, + 0x4bb0a1bf, 0xfcad60bb, 0x258b23b6, 0x9296e2b2, + 0x2f2bad8a, 0x98366c8e, 0x41102f83, 0xf60dee87, + 0xf35da999, 0x4440689d, 0x9d662b90, 0x2a7bea94, + 0xe71db4e0, 0x500075e4, 0x892636e9, 0x3e3bf7ed, + 0x3b6bb0f3, 0x8c7671f7, 0x555032fa, 0xe24df3fe, + 0x5ff0bcc6, 0xe8ed7dc2, 0x31cb3ecf, 0x86d6ffcb, + 0x8386b8d5, 0x349b79d1, 0xedbd3adc, 0x5aa0fbd8, + 0xeee00c69, 0x59fdcd6d, 0x80db8e60, 0x37c64f64, + 0x3296087a, 0x858bc97e, 0x5cad8a73, 0xebb04b77, + 0x560d044f, 0xe110c54b, 0x38368646, 0x8f2b4742, + 0x8a7b005c, 0x3d66c158, 0xe4408255, 0x535d4351, + 0x9e3b1d25, 0x2926dc21, 0xf0009f2c, 0x471d5e28, + 0x424d1936, 0xf550d832, 0x2c769b3f, 0x9b6b5a3b, + 0x26d61503, 0x91cbd407, 0x48ed970a, 0xfff0560e, + 0xfaa01110, 0x4dbdd014, 0x949b9319, 0x2386521d, + 0x0e562ff1, 0xb94beef5, 0x606dadf8, 0xd7706cfc, + 0xd2202be2, 0x653deae6, 0xbc1ba9eb, 0x0b0668ef, + 0xb6bb27d7, 0x01a6e6d3, 0xd880a5de, 0x6f9d64da, + 0x6acd23c4, 0xddd0e2c0, 0x04f6a1cd, 0xb3eb60c9, + 0x7e8d3ebd, 0xc990ffb9, 0x10b6bcb4, 0xa7ab7db0, + 0xa2fb3aae, 0x15e6fbaa, 0xccc0b8a7, 0x7bdd79a3, + 0xc660369b, 0x717df79f, 0xa85bb492, 0x1f467596, + 0x1a163288, 0xad0bf38c, 0x742db081, 0xc3307185, + 0x99908a5d, 0x2e8d4b59, 0xf7ab0854, 0x40b6c950, + 0x45e68e4e, 0xf2fb4f4a, 0x2bdd0c47, 0x9cc0cd43, + 0x217d827b, 0x9660437f, 0x4f460072, 0xf85bc176, + 0xfd0b8668, 0x4a16476c, 0x93300461, 0x242dc565, + 0xe94b9b11, 0x5e565a15, 0x87701918, 0x306dd81c, + 0x353d9f02, 0x82205e06, 0x5b061d0b, 0xec1bdc0f, + 0x51a69337, 0xe6bb5233, 0x3f9d113e, 0x8880d03a, + 0x8dd09724, 0x3acd5620, 0xe3eb152d, 0x54f6d429, + 0x7926a9c5, 0xce3b68c1, 0x171d2bcc, 0xa000eac8, + 0xa550add6, 0x124d6cd2, 0xcb6b2fdf, 0x7c76eedb, + 0xc1cba1e3, 0x76d660e7, 0xaff023ea, 0x18ede2ee, + 0x1dbda5f0, 0xaaa064f4, 0x738627f9, 0xc49be6fd, + 0x09fdb889, 0xbee0798d, 0x67c63a80, 0xd0dbfb84, + 0xd58bbc9a, 0x62967d9e, 0xbbb03e93, 0x0cadff97, + 0xb110b0af, 0x060d71ab, 0xdf2b32a6, 0x6836f3a2, + 0x6d66b4bc, 0xda7b75b8, 0x035d36b5, 0xb440f7b1 +}; + +const uint32_t crc_table_cksum_big[1024] PROGMEM = { + 0x00000000, 0xb71dc104, 0x6e3b8209, 0xd926430d, + 0xdc760413, 0x6b6bc517, 0xb24d861a, 0x0550471e, + 0xb8ed0826, 0x0ff0c922, 0xd6d68a2f, 0x61cb4b2b, + 0x649b0c35, 0xd386cd31, 0x0aa08e3c, 0xbdbd4f38, + 0x70db114c, 0xc7c6d048, 0x1ee09345, 0xa9fd5241, + 0xacad155f, 0x1bb0d45b, 0xc2969756, 0x758b5652, + 0xc836196a, 0x7f2bd86e, 0xa60d9b63, 0x11105a67, + 0x14401d79, 0xa35ddc7d, 0x7a7b9f70, 0xcd665e74, + 0xe0b62398, 0x57abe29c, 0x8e8da191, 0x39906095, + 0x3cc0278b, 0x8bdde68f, 0x52fba582, 0xe5e66486, + 0x585b2bbe, 0xef46eaba, 0x3660a9b7, 0x817d68b3, + 0x842d2fad, 0x3330eea9, 0xea16ada4, 0x5d0b6ca0, + 0x906d32d4, 0x2770f3d0, 0xfe56b0dd, 0x494b71d9, + 0x4c1b36c7, 0xfb06f7c3, 0x2220b4ce, 0x953d75ca, + 0x28803af2, 0x9f9dfbf6, 0x46bbb8fb, 0xf1a679ff, + 0xf4f63ee1, 0x43ebffe5, 0x9acdbce8, 0x2dd07dec, + 0x77708634, 0xc06d4730, 0x194b043d, 0xae56c539, + 0xab068227, 0x1c1b4323, 0xc53d002e, 0x7220c12a, + 0xcf9d8e12, 0x78804f16, 0xa1a60c1b, 0x16bbcd1f, + 0x13eb8a01, 0xa4f64b05, 0x7dd00808, 0xcacdc90c, + 0x07ab9778, 0xb0b6567c, 0x69901571, 0xde8dd475, + 0xdbdd936b, 0x6cc0526f, 0xb5e61162, 0x02fbd066, + 0xbf469f5e, 0x085b5e5a, 0xd17d1d57, 0x6660dc53, + 0x63309b4d, 0xd42d5a49, 0x0d0b1944, 0xba16d840, + 0x97c6a5ac, 0x20db64a8, 0xf9fd27a5, 0x4ee0e6a1, + 0x4bb0a1bf, 0xfcad60bb, 0x258b23b6, 0x9296e2b2, + 0x2f2bad8a, 0x98366c8e, 0x41102f83, 0xf60dee87, + 0xf35da999, 0x4440689d, 0x9d662b90, 0x2a7bea94, + 0xe71db4e0, 0x500075e4, 0x892636e9, 0x3e3bf7ed, + 0x3b6bb0f3, 0x8c7671f7, 0x555032fa, 0xe24df3fe, + 0x5ff0bcc6, 0xe8ed7dc2, 0x31cb3ecf, 0x86d6ffcb, + 0x8386b8d5, 0x349b79d1, 0xedbd3adc, 0x5aa0fbd8, + 0xeee00c69, 0x59fdcd6d, 0x80db8e60, 0x37c64f64, + 0x3296087a, 0x858bc97e, 0x5cad8a73, 0xebb04b77, + 0x560d044f, 0xe110c54b, 0x38368646, 0x8f2b4742, + 0x8a7b005c, 0x3d66c158, 0xe4408255, 0x535d4351, + 0x9e3b1d25, 0x2926dc21, 0xf0009f2c, 0x471d5e28, + 0x424d1936, 0xf550d832, 0x2c769b3f, 0x9b6b5a3b, + 0x26d61503, 0x91cbd407, 0x48ed970a, 0xfff0560e, + 0xfaa01110, 0x4dbdd014, 0x949b9319, 0x2386521d, + 0x0e562ff1, 0xb94beef5, 0x606dadf8, 0xd7706cfc, + 0xd2202be2, 0x653deae6, 0xbc1ba9eb, 0x0b0668ef, + 0xb6bb27d7, 0x01a6e6d3, 0xd880a5de, 0x6f9d64da, + 0x6acd23c4, 0xddd0e2c0, 0x04f6a1cd, 0xb3eb60c9, + 0x7e8d3ebd, 0xc990ffb9, 0x10b6bcb4, 0xa7ab7db0, + 0xa2fb3aae, 0x15e6fbaa, 0xccc0b8a7, 0x7bdd79a3, + 0xc660369b, 0x717df79f, 0xa85bb492, 0x1f467596, + 0x1a163288, 0xad0bf38c, 0x742db081, 0xc3307185, + 0x99908a5d, 0x2e8d4b59, 0xf7ab0854, 0x40b6c950, + 0x45e68e4e, 0xf2fb4f4a, 0x2bdd0c47, 0x9cc0cd43, + 0x217d827b, 0x9660437f, 0x4f460072, 0xf85bc176, + 0xfd0b8668, 0x4a16476c, 0x93300461, 0x242dc565, + 0xe94b9b11, 0x5e565a15, 0x87701918, 0x306dd81c, + 0x353d9f02, 0x82205e06, 0x5b061d0b, 0xec1bdc0f, + 0x51a69337, 0xe6bb5233, 0x3f9d113e, 0x8880d03a, + 0x8dd09724, 0x3acd5620, 0xe3eb152d, 0x54f6d429, + 0x7926a9c5, 0xce3b68c1, 0x171d2bcc, 0xa000eac8, + 0xa550add6, 0x124d6cd2, 0xcb6b2fdf, 0x7c76eedb, + 0xc1cba1e3, 0x76d660e7, 0xaff023ea, 0x18ede2ee, + 0x1dbda5f0, 0xaaa064f4, 0x738627f9, 0xc49be6fd, + 0x09fdb889, 0xbee0798d, 0x67c63a80, 0xd0dbfb84, + 0xd58bbc9a, 0x62967d9e, 0xbbb03e93, 0x0cadff97, + 0xb110b0af, 0x060d71ab, 0xdf2b32a6, 0x6836f3a2, + 0x6d66b4bc, 0xda7b75b8, 0x035d36b5, 0xb440f7b1, + 0x00000000, 0xdcc119d2, 0x0f9ef2a0, 0xd35feb72, + 0xa9212445, 0x75e03d97, 0xa6bfd6e5, 0x7a7ecf37, + 0x5243488a, 0x8e825158, 0x5dddba2a, 0x811ca3f8, + 0xfb626ccf, 0x27a3751d, 0xf4fc9e6f, 0x283d87bd, + 0x139b5110, 0xcf5a48c2, 0x1c05a3b0, 0xc0c4ba62, + 0xbaba7555, 0x667b6c87, 0xb52487f5, 0x69e59e27, + 0x41d8199a, 0x9d190048, 0x4e46eb3a, 0x9287f2e8, + 0xe8f93ddf, 0x3438240d, 0xe767cf7f, 0x3ba6d6ad, + 0x2636a320, 0xfaf7baf2, 0x29a85180, 0xf5694852, + 0x8f178765, 0x53d69eb7, 0x808975c5, 0x5c486c17, + 0x7475ebaa, 0xa8b4f278, 0x7beb190a, 0xa72a00d8, + 0xdd54cfef, 0x0195d63d, 0xd2ca3d4f, 0x0e0b249d, + 0x35adf230, 0xe96cebe2, 0x3a330090, 0xe6f21942, + 0x9c8cd675, 0x404dcfa7, 0x931224d5, 0x4fd33d07, + 0x67eebaba, 0xbb2fa368, 0x6870481a, 0xb4b151c8, + 0xcecf9eff, 0x120e872d, 0xc1516c5f, 0x1d90758d, + 0x4c6c4641, 0x90ad5f93, 0x43f2b4e1, 0x9f33ad33, + 0xe54d6204, 0x398c7bd6, 0xead390a4, 0x36128976, + 0x1e2f0ecb, 0xc2ee1719, 0x11b1fc6b, 0xcd70e5b9, + 0xb70e2a8e, 0x6bcf335c, 0xb890d82e, 0x6451c1fc, + 0x5ff71751, 0x83360e83, 0x5069e5f1, 0x8ca8fc23, + 0xf6d63314, 0x2a172ac6, 0xf948c1b4, 0x2589d866, + 0x0db45fdb, 0xd1754609, 0x022aad7b, 0xdeebb4a9, + 0xa4957b9e, 0x7854624c, 0xab0b893e, 0x77ca90ec, + 0x6a5ae561, 0xb69bfcb3, 0x65c417c1, 0xb9050e13, + 0xc37bc124, 0x1fbad8f6, 0xcce53384, 0x10242a56, + 0x3819adeb, 0xe4d8b439, 0x37875f4b, 0xeb464699, + 0x913889ae, 0x4df9907c, 0x9ea67b0e, 0x426762dc, + 0x79c1b471, 0xa500ada3, 0x765f46d1, 0xaa9e5f03, + 0xd0e09034, 0x0c2189e6, 0xdf7e6294, 0x03bf7b46, + 0x2b82fcfb, 0xf743e529, 0x241c0e5b, 0xf8dd1789, + 0x82a3d8be, 0x5e62c16c, 0x8d3d2a1e, 0x51fc33cc, + 0x98d88c82, 0x44199550, 0x97467e22, 0x4b8767f0, + 0x31f9a8c7, 0xed38b115, 0x3e675a67, 0xe2a643b5, + 0xca9bc408, 0x165addda, 0xc50536a8, 0x19c42f7a, + 0x63bae04d, 0xbf7bf99f, 0x6c2412ed, 0xb0e50b3f, + 0x8b43dd92, 0x5782c440, 0x84dd2f32, 0x581c36e0, + 0x2262f9d7, 0xfea3e005, 0x2dfc0b77, 0xf13d12a5, + 0xd9009518, 0x05c18cca, 0xd69e67b8, 0x0a5f7e6a, + 0x7021b15d, 0xace0a88f, 0x7fbf43fd, 0xa37e5a2f, + 0xbeee2fa2, 0x622f3670, 0xb170dd02, 0x6db1c4d0, + 0x17cf0be7, 0xcb0e1235, 0x1851f947, 0xc490e095, + 0xecad6728, 0x306c7efa, 0xe3339588, 0x3ff28c5a, + 0x458c436d, 0x994d5abf, 0x4a12b1cd, 0x96d3a81f, + 0xad757eb2, 0x71b46760, 0xa2eb8c12, 0x7e2a95c0, + 0x04545af7, 0xd8954325, 0x0bcaa857, 0xd70bb185, + 0xff363638, 0x23f72fea, 0xf0a8c498, 0x2c69dd4a, + 0x5617127d, 0x8ad60baf, 0x5989e0dd, 0x8548f90f, + 0xd4b4cac3, 0x0875d311, 0xdb2a3863, 0x07eb21b1, + 0x7d95ee86, 0xa154f754, 0x720b1c26, 0xaeca05f4, + 0x86f78249, 0x5a369b9b, 0x896970e9, 0x55a8693b, + 0x2fd6a60c, 0xf317bfde, 0x204854ac, 0xfc894d7e, + 0xc72f9bd3, 0x1bee8201, 0xc8b16973, 0x147070a1, + 0x6e0ebf96, 0xb2cfa644, 0x61904d36, 0xbd5154e4, + 0x956cd359, 0x49adca8b, 0x9af221f9, 0x4633382b, + 0x3c4df71c, 0xe08ceece, 0x33d305bc, 0xef121c6e, + 0xf28269e3, 0x2e437031, 0xfd1c9b43, 0x21dd8291, + 0x5ba34da6, 0x87625474, 0x543dbf06, 0x88fca6d4, + 0xa0c12169, 0x7c0038bb, 0xaf5fd3c9, 0x739eca1b, + 0x09e0052c, 0xd5211cfe, 0x067ef78c, 0xdabfee5e, + 0xe11938f3, 0x3dd82121, 0xee87ca53, 0x3246d381, + 0x48381cb6, 0x94f90564, 0x47a6ee16, 0x9b67f7c4, + 0xb35a7079, 0x6f9b69ab, 0xbcc482d9, 0x60059b0b, + 0x1a7b543c, 0xc6ba4dee, 0x15e5a69c, 0xc924bf4e, + 0x00000000, 0x87acd801, 0x0e59b103, 0x89f56902, + 0x1cb26207, 0x9b1eba06, 0x12ebd304, 0x95470b05, + 0x3864c50e, 0xbfc81d0f, 0x363d740d, 0xb191ac0c, + 0x24d6a709, 0xa37a7f08, 0x2a8f160a, 0xad23ce0b, + 0x70c88a1d, 0xf764521c, 0x7e913b1e, 0xf93de31f, + 0x6c7ae81a, 0xebd6301b, 0x62235919, 0xe58f8118, + 0x48ac4f13, 0xcf009712, 0x46f5fe10, 0xc1592611, + 0x541e2d14, 0xd3b2f515, 0x5a479c17, 0xddeb4416, + 0xe090153b, 0x673ccd3a, 0xeec9a438, 0x69657c39, + 0xfc22773c, 0x7b8eaf3d, 0xf27bc63f, 0x75d71e3e, + 0xd8f4d035, 0x5f580834, 0xd6ad6136, 0x5101b937, + 0xc446b232, 0x43ea6a33, 0xca1f0331, 0x4db3db30, + 0x90589f26, 0x17f44727, 0x9e012e25, 0x19adf624, + 0x8ceafd21, 0x0b462520, 0x82b34c22, 0x051f9423, + 0xa83c5a28, 0x2f908229, 0xa665eb2b, 0x21c9332a, + 0xb48e382f, 0x3322e02e, 0xbad7892c, 0x3d7b512d, + 0xc0212b76, 0x478df377, 0xce789a75, 0x49d44274, + 0xdc934971, 0x5b3f9170, 0xd2caf872, 0x55662073, + 0xf845ee78, 0x7fe93679, 0xf61c5f7b, 0x71b0877a, + 0xe4f78c7f, 0x635b547e, 0xeaae3d7c, 0x6d02e57d, + 0xb0e9a16b, 0x3745796a, 0xbeb01068, 0x391cc869, + 0xac5bc36c, 0x2bf71b6d, 0xa202726f, 0x25aeaa6e, + 0x888d6465, 0x0f21bc64, 0x86d4d566, 0x01780d67, + 0x943f0662, 0x1393de63, 0x9a66b761, 0x1dca6f60, + 0x20b13e4d, 0xa71de64c, 0x2ee88f4e, 0xa944574f, + 0x3c035c4a, 0xbbaf844b, 0x325aed49, 0xb5f63548, + 0x18d5fb43, 0x9f792342, 0x168c4a40, 0x91209241, + 0x04679944, 0x83cb4145, 0x0a3e2847, 0x8d92f046, + 0x5079b450, 0xd7d56c51, 0x5e200553, 0xd98cdd52, + 0x4ccbd657, 0xcb670e56, 0x42926754, 0xc53ebf55, + 0x681d715e, 0xefb1a95f, 0x6644c05d, 0xe1e8185c, + 0x74af1359, 0xf303cb58, 0x7af6a25a, 0xfd5a7a5b, + 0x804356ec, 0x07ef8eed, 0x8e1ae7ef, 0x09b63fee, + 0x9cf134eb, 0x1b5decea, 0x92a885e8, 0x15045de9, + 0xb82793e2, 0x3f8b4be3, 0xb67e22e1, 0x31d2fae0, + 0xa495f1e5, 0x233929e4, 0xaacc40e6, 0x2d6098e7, + 0xf08bdcf1, 0x772704f0, 0xfed26df2, 0x797eb5f3, + 0xec39bef6, 0x6b9566f7, 0xe2600ff5, 0x65ccd7f4, + 0xc8ef19ff, 0x4f43c1fe, 0xc6b6a8fc, 0x411a70fd, + 0xd45d7bf8, 0x53f1a3f9, 0xda04cafb, 0x5da812fa, + 0x60d343d7, 0xe77f9bd6, 0x6e8af2d4, 0xe9262ad5, + 0x7c6121d0, 0xfbcdf9d1, 0x723890d3, 0xf59448d2, + 0x58b786d9, 0xdf1b5ed8, 0x56ee37da, 0xd142efdb, + 0x4405e4de, 0xc3a93cdf, 0x4a5c55dd, 0xcdf08ddc, + 0x101bc9ca, 0x97b711cb, 0x1e4278c9, 0x99eea0c8, + 0x0ca9abcd, 0x8b0573cc, 0x02f01ace, 0x855cc2cf, + 0x287f0cc4, 0xafd3d4c5, 0x2626bdc7, 0xa18a65c6, + 0x34cd6ec3, 0xb361b6c2, 0x3a94dfc0, 0xbd3807c1, + 0x40627d9a, 0xc7cea59b, 0x4e3bcc99, 0xc9971498, + 0x5cd01f9d, 0xdb7cc79c, 0x5289ae9e, 0xd525769f, + 0x7806b894, 0xffaa6095, 0x765f0997, 0xf1f3d196, + 0x64b4da93, 0xe3180292, 0x6aed6b90, 0xed41b391, + 0x30aaf787, 0xb7062f86, 0x3ef34684, 0xb95f9e85, + 0x2c189580, 0xabb44d81, 0x22412483, 0xa5edfc82, + 0x08ce3289, 0x8f62ea88, 0x0697838a, 0x813b5b8b, + 0x147c508e, 0x93d0888f, 0x1a25e18d, 0x9d89398c, + 0xa0f268a1, 0x275eb0a0, 0xaeabd9a2, 0x290701a3, + 0xbc400aa6, 0x3becd2a7, 0xb219bba5, 0x35b563a4, + 0x9896adaf, 0x1f3a75ae, 0x96cf1cac, 0x1163c4ad, + 0x8424cfa8, 0x038817a9, 0x8a7d7eab, 0x0dd1a6aa, + 0xd03ae2bc, 0x57963abd, 0xde6353bf, 0x59cf8bbe, + 0xcc8880bb, 0x4b2458ba, 0xc2d131b8, 0x457de9b9, + 0xe85e27b2, 0x6ff2ffb3, 0xe60796b1, 0x61ab4eb0, + 0xf4ec45b5, 0x73409db4, 0xfab5f4b6, 0x7d192cb7, + 0x00000000, 0xb79a6ddc, 0xd9281abc, 0x6eb27760, + 0x054cf57c, 0xb2d698a0, 0xdc64efc0, 0x6bfe821c, + 0x0a98eaf9, 0xbd028725, 0xd3b0f045, 0x642a9d99, + 0x0fd41f85, 0xb84e7259, 0xd6fc0539, 0x616668e5, + 0xa32d14f7, 0x14b7792b, 0x7a050e4b, 0xcd9f6397, + 0xa661e18b, 0x11fb8c57, 0x7f49fb37, 0xc8d396eb, + 0xa9b5fe0e, 0x1e2f93d2, 0x709de4b2, 0xc707896e, + 0xacf90b72, 0x1b6366ae, 0x75d111ce, 0xc24b7c12, + 0xf146e9ea, 0x46dc8436, 0x286ef356, 0x9ff49e8a, + 0xf40a1c96, 0x4390714a, 0x2d22062a, 0x9ab86bf6, + 0xfbde0313, 0x4c446ecf, 0x22f619af, 0x956c7473, + 0xfe92f66f, 0x49089bb3, 0x27baecd3, 0x9020810f, + 0x526bfd1d, 0xe5f190c1, 0x8b43e7a1, 0x3cd98a7d, + 0x57270861, 0xe0bd65bd, 0x8e0f12dd, 0x39957f01, + 0x58f317e4, 0xef697a38, 0x81db0d58, 0x36416084, + 0x5dbfe298, 0xea258f44, 0x8497f824, 0x330d95f8, + 0x559013d1, 0xe20a7e0d, 0x8cb8096d, 0x3b2264b1, + 0x50dce6ad, 0xe7468b71, 0x89f4fc11, 0x3e6e91cd, + 0x5f08f928, 0xe89294f4, 0x8620e394, 0x31ba8e48, + 0x5a440c54, 0xedde6188, 0x836c16e8, 0x34f67b34, + 0xf6bd0726, 0x41276afa, 0x2f951d9a, 0x980f7046, + 0xf3f1f25a, 0x446b9f86, 0x2ad9e8e6, 0x9d43853a, + 0xfc25eddf, 0x4bbf8003, 0x250df763, 0x92979abf, + 0xf96918a3, 0x4ef3757f, 0x2041021f, 0x97db6fc3, + 0xa4d6fa3b, 0x134c97e7, 0x7dfee087, 0xca648d5b, + 0xa19a0f47, 0x1600629b, 0x78b215fb, 0xcf287827, + 0xae4e10c2, 0x19d47d1e, 0x77660a7e, 0xc0fc67a2, + 0xab02e5be, 0x1c988862, 0x722aff02, 0xc5b092de, + 0x07fbeecc, 0xb0618310, 0xded3f470, 0x694999ac, + 0x02b71bb0, 0xb52d766c, 0xdb9f010c, 0x6c056cd0, + 0x0d630435, 0xbaf969e9, 0xd44b1e89, 0x63d17355, + 0x082ff149, 0xbfb59c95, 0xd107ebf5, 0x669d8629, + 0x1d3de6a6, 0xaaa78b7a, 0xc415fc1a, 0x738f91c6, + 0x187113da, 0xafeb7e06, 0xc1590966, 0x76c364ba, + 0x17a50c5f, 0xa03f6183, 0xce8d16e3, 0x79177b3f, + 0x12e9f923, 0xa57394ff, 0xcbc1e39f, 0x7c5b8e43, + 0xbe10f251, 0x098a9f8d, 0x6738e8ed, 0xd0a28531, + 0xbb5c072d, 0x0cc66af1, 0x62741d91, 0xd5ee704d, + 0xb48818a8, 0x03127574, 0x6da00214, 0xda3a6fc8, + 0xb1c4edd4, 0x065e8008, 0x68ecf768, 0xdf769ab4, + 0xec7b0f4c, 0x5be16290, 0x355315f0, 0x82c9782c, + 0xe937fa30, 0x5ead97ec, 0x301fe08c, 0x87858d50, + 0xe6e3e5b5, 0x51798869, 0x3fcbff09, 0x885192d5, + 0xe3af10c9, 0x54357d15, 0x3a870a75, 0x8d1d67a9, + 0x4f561bbb, 0xf8cc7667, 0x967e0107, 0x21e46cdb, + 0x4a1aeec7, 0xfd80831b, 0x9332f47b, 0x24a899a7, + 0x45cef142, 0xf2549c9e, 0x9ce6ebfe, 0x2b7c8622, + 0x4082043e, 0xf71869e2, 0x99aa1e82, 0x2e30735e, + 0x48adf577, 0xff3798ab, 0x9185efcb, 0x261f8217, + 0x4de1000b, 0xfa7b6dd7, 0x94c91ab7, 0x2353776b, + 0x42351f8e, 0xf5af7252, 0x9b1d0532, 0x2c8768ee, + 0x4779eaf2, 0xf0e3872e, 0x9e51f04e, 0x29cb9d92, + 0xeb80e180, 0x5c1a8c5c, 0x32a8fb3c, 0x853296e0, + 0xeecc14fc, 0x59567920, 0x37e40e40, 0x807e639c, + 0xe1180b79, 0x568266a5, 0x383011c5, 0x8faa7c19, + 0xe454fe05, 0x53ce93d9, 0x3d7ce4b9, 0x8ae68965, + 0xb9eb1c9d, 0x0e717141, 0x60c30621, 0xd7596bfd, + 0xbca7e9e1, 0x0b3d843d, 0x658ff35d, 0xd2159e81, + 0xb373f664, 0x04e99bb8, 0x6a5becd8, 0xddc18104, + 0xb63f0318, 0x01a56ec4, 0x6f1719a4, 0xd88d7478, + 0x1ac6086a, 0xad5c65b6, 0xc3ee12d6, 0x74747f0a, + 0x1f8afd16, 0xa81090ca, 0xc6a2e7aa, 0x71388a76, + 0x105ee293, 0xa7c48f4f, 0xc976f82f, 0x7eec95f3, + 0x151217ef, 0xa2887a33, 0xcc3a0d53, 0x7ba0608f +}; +#endif diff --git a/Arduino/SelfomatController/FastCRChw.cpp b/Arduino/SelfomatController/FastCRChw.cpp new file mode 100644 index 0000000..eeda47a --- /dev/null +++ b/Arduino/SelfomatController/FastCRChw.cpp @@ -0,0 +1,453 @@ +/* FastCRC library code is placed under the MIT license + * Copyright (c) 2014,2015 Frank Bösing + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// +// HW-calculations are 32BIT +// +// Thanks to: +// - Catalogue of parametrised CRC algorithms, CRC RevEng +// http://reveng.sourceforge.net/crc-catalogue/ +// +// - Danjel McGougan (CRC-Table-Generator) +// + +#include "Arduino.h" +#if defined(KINETISK) + +#include "mk20dx128.h" +#include "FastCRC.h" + +// =============================================== + +typedef struct { + union { + uint32_t CRC; //CRC Data register + struct { + uint16_t CRC16; + uint16_t CRC16_1; + }; + struct { + uint8_t CRC8; + uint8_t CRC8_1; + uint8_t CRC8_2; + uint8_t CRC8_3; + }; + }; + uint32_t GPOLY; //CRC Polynomial register + uint32_t CTRL; //CRC Control register +} CRC_T; + +static volatile CRC_T * const rCRC = (CRC_T *)0x40032000; + +#define CRC_CTRL_WAS 25 // Write CRC Data Register As Seed(1) / Data(0) +#define CRC_CTRL_TCRC 24 // Width of CRC protocol (0=16 BIT, 1=32 BIT) +#define CRC_CTRL_TOTR1 29 // TOTR[1] + +// ================= 7-BIT CRC =================== +/** Constructor + * Enables CRC-clock + */ +FastCRC7::FastCRC7(){ + SIM_SCGC6 |= SIM_SCGC6_CRC; +} + +/** CRC 7 + * MultiMediaCard interface + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC7::crc7(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75 + return (generic(0x09, 0, CRC_FLAG_NOREFLECT, data, datalen)); +} + +/** Update + * Call for subsequent calculations with previous seed + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC7::update(const uint8_t *data, const uint16_t datalen) +{ + + const uint8_t *src = data; + const uint8_t *target = src + datalen; + + while (((uintptr_t)src & 0x03) != 0 && (src < target)) { + rCRC->CRC8_3 = *src++; //Write 8 BIT + } + + while (src <= target-4) { + rCRC->CRC = *( uint32_t *)src; //Write 32 BIT + src += 4; + } + + while (src < target) { + rCRC->CRC8_3 = *src++; //Write 8 Bit + } + +//TODO: Check handling of CRC_CTRL_TOTR1 for other CRC7s +/* + if (rCRC->CTRL & (1<CRC8 >> 1; + else +*/ + return rCRC->CRC8_3 >> 1; +} + +/** generic function for all 7-Bit CRCs + * @param polynom Polynom + * @param seed Seed + * @param flags Flags + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC7::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const uint16_t datalen) +{ + + rCRC->CTRL = flags | (1<GPOLY = ((uint32_t)polynom)<<(24 + 1); // Set polynom + rCRC->CRC = ((uint32_t)seed<<(24 + 1)); // Write seed + rCRC->CTRL = flags | (1<CRC8_3 = *src++; //Write 8 BIT + } + + while (src <= target-4) { + rCRC->CRC = *( uint32_t *)src; //Write 32 BIT + src += 4; + } + + while (src < target) { + rCRC->CRC8_3 = *src++; //Write 8 Bit + } + + if (rCRC->CTRL & (1<CRC8; + else + return rCRC->CRC8_3; +} + +/** generic function for all 8-Bit CRCs + * @param polynom Polynom + * @param seed Seed + * @param flags Flags + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC8::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const uint16_t datalen) +{ + + rCRC->CTRL = flags | (1<GPOLY = ((uint32_t)polynom)<<24; // Set polynom + rCRC->CRC = ((uint32_t)seed<<24); // Write seed + rCRC->CTRL = flags | (1<CRC8_3 = *src++; //Write 8 BIT + } + + while (src <= target-4) { + rCRC->CRC = *( uint32_t *)src; //Write 32 BIT + src += 4; + } + + while (src < target) { + rCRC->CRC8_3 = *src++; //Write 8 Bit + } + + if (rCRC->CTRL & (1<CRC16; + else + return rCRC->CRC16_1; +} + +/** generic function for all 16-Bit CRCs + * @param polynom Polynom + * @param seed Seed + * @param flags Flags + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen) +{ + + rCRC->CTRL = flags | (1<GPOLY = ((uint32_t)polynom)<<16; // set polynom + rCRC->CRC = ((uint32_t)seed<<16); // this is the seed + rCRC->CTRL = flags | (1<CRC8_3 = *src++; //Write 8 BIT + } + + while (src <= target-4) { + rCRC->CRC = *( uint32_t *)src; //Write 32 BIT + src += 4; + } + + while (src < target) { + rCRC->CRC8_3 = *src++; //Write 8 Bit + } + + return rCRC->CRC; +} + +/** generic function for all 32-Bit CRCs + * @param polynom Polynom + * @param seed Seed + * @param flags Flags + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint32_t FastCRC32::generic(const uint32_t polynom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen) +{ + + rCRC->CTRL = flags | (1<GPOLY = polynom; // Set polynom + rCRC->CRC = seed; // This is the seed + rCRC->CTRL = flags | (1<> 1; +} + +uint8_t FastCRC7::crc7(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75 + seed = 0x00; + return crc7_upd(data, datalen); +} + +// ================= 8-BIT CRC =================== + +/** Constructor + */ +FastCRC8::FastCRC8(){} + +/** SMBUS CRC + * aka CRC-8 + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC8::smbus_upd(const uint8_t *data, uint16_t datalen) +{ + uint8_t crc = seed; + if (datalen) do { + crc = pgm_read_byte(&crc_table_smbus[crc ^ *data]); + data++; + } while (--datalen); + seed = crc; + return crc; +} + +uint8_t FastCRC8::smbus(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4 + seed = 0x00; + return smbus_upd(data, datalen); +} + +/** MAXIM 8-Bit CRC + * equivalent to _crc_ibutton_update() in crc16.h from avr_libc + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint8_t FastCRC8::maxim_upd(const uint8_t *data, uint16_t datalen) +{ + uint8_t crc = seed; + if (datalen) do { + crc = pgm_read_byte(&crc_table_maxim[crc ^ *data]); + data++; + } while (--datalen); + seed = crc; + return crc; +} +uint8_t FastCRC8::maxim(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1 + seed = 0x00; + return maxim_upd(data, datalen); +} + +// ================= 16-BIT CRC =================== +/** Constructor + */ +FastCRC16::FastCRC16(){} + +#define crc_n4(crc, data, table) crc ^= data; \ + crc = pgm_read_word(&table[(crc & 0xff) + 0x300]) ^ \ + pgm_read_word(&table[((crc >> 8) & 0xff) + 0x200]) ^ \ + pgm_read_word(&table[((data >> 16) & 0xff) + 0x100]) ^ \ + pgm_read_word(&table[data >> 24]); + +/** CCITT + * Alias "false CCITT" + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::ccitt_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]); + } + + seed = crc; + crc = REV16(crc); + + return crc; +} +uint16_t FastCRC16::ccitt(const uint8_t *data,const uint16_t datalen) +{ + // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 + seed = 0xffff; + return ccitt_upd(data, datalen); +} + +/** MCRF4XX + * equivalent to _crc_ccitt_update() in crc16.h from avr_libc + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ + +uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]); + } + + seed = crc; + return crc; +} + +uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const uint16_t datalen) +{ + // poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91 + seed = 0xffff; + return mcrf4xx_upd(data, datalen); +} + +/** MODBUS + * equivalent to _crc_16_update() in crc16.h from avr_libc + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::modbus_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]); + } + + seed = crc; + return crc; +} + +uint16_t FastCRC16::modbus(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 + seed = 0xffff; + return modbus_upd(data, datalen); +} + +/** KERMIT + * Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::kermit_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]); + } + + seed = crc; + return crc; +} + +uint16_t FastCRC16::kermit(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 + // sometimes byteswapped presentation of result + seed = 0x0000; + return kermit_upd(data, datalen); +} + +/** XMODEM + * Alias ZMODEM, CRC-16/ACORN + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::xmodem_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]); + } + + seed = crc; + crc = REV16(crc); + return crc; +} + +uint16_t FastCRC16::xmodem(const uint8_t *data, const uint16_t datalen) +{ + //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 + seed = 0x0000; + return xmodem_upd(data, datalen); +} + +/** X25 + * Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +uint16_t FastCRC16::x25_upd(const uint8_t *data, uint16_t len) +{ + + uint16_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25); + crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25); + crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25); + crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25); + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]); + } + + seed = crc; + crc = ~crc; + + return crc; +} + +uint16_t FastCRC16::x25(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e + seed = 0xffff; + return x25_upd(data, datalen); +} + + + + + +// ================= 32-BIT CRC =================== +/** Constructor + */ +FastCRC32::FastCRC32(){} + +#define crc_n4d(crc, data, table) crc ^= data; \ + crc = pgm_read_dword(&table[(crc & 0xff) + 0x300]) ^ \ + pgm_read_dword(&table[((crc >> 8) & 0xff) + 0x200]) ^ \ + pgm_read_dword(&table[((crc >> 16) & 0xff) + 0x100]) ^ \ + pgm_read_dword(&table[(crc >> 24) & 0xff]); + +#define crcsm_n4d(crc, data, table) crc ^= data; \ + crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \ + crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \ + crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \ + crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); + +/** CRC32 + * Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3 + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ +#if CRC_BIGTABLES +#define CRC_TABLE_CRC32 crc_table_crc32_big +#else +#define CRC_TABLE_CRC32 crc_table_crc32 +#endif + +uint32_t FastCRC32::crc32_upd(const uint8_t *data, uint16_t len) +{ + + uint32_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + #if CRC_BIGTABLES + crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32); + crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32); + crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32); + crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32); + #else + crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32); + crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32); + crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32); + crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32); + #endif + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]); + } + + seed = crc; + crc = ~crc; + + return crc; +} + +uint32_t FastCRC32::crc32(const uint8_t *data, const uint16_t datalen) +{ + // poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926 + seed = 0xffffffff; + return crc32_upd(data, datalen); +} + +/** CKSUM + * Alias CRC-32/POSIX + * @param data Pointer to Data + * @param datalen Length of Data + * @return CRC value + */ + #if CRC_BIGTABLES +#define CRC_TABLE_CKSUM crc_table_cksum_big +#else +#define CRC_TABLE_CKSUM crc_table_cksum +#endif +uint32_t FastCRC32::cksum_upd(const uint8_t *data, uint16_t len) +{ + + uint32_t crc = seed; + + while (((uintptr_t)data & 3) && len) { + crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]); + len--; + } + + while (len >= 16) { + len -= 16; + #if CRC_BIGTABLES + crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM); + crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM); + crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM); + crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM); + #else + crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM); + crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM); + crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM); + crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM); + #endif + data += 16; + } + + while (len--) { + crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]); + } + + seed = crc; + crc = ~REV32(crc); + return crc; +} + +uint32_t FastCRC32::cksum(const uint8_t *data, const uint16_t datalen) +{ + // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680 + seed = 0x00; + return cksum_upd(data, datalen); +} + +#endif // #if !defined(KINETISK) diff --git a/Arduino/SelfomatController/FastMath.h b/Arduino/SelfomatController/FastMath.h new file mode 100644 index 0000000..f1676c6 --- /dev/null +++ b/Arduino/SelfomatController/FastMath.h @@ -0,0 +1,74 @@ +#ifndef FAST_MATH_H +#define FAST_MATH_H + + +// 91 x 2 bytes ==> 182 bytes +unsigned int isinTable16[] = { + 0, 1144, 2287, 3430, 4571, 5712, 6850, 7987, 9121, 10252, 11380, + 12505, 13625, 14742, 15854, 16962, 18064, 19161, 20251, 21336, 22414, + 23486, 24550, 25607, 26655, 27696, 28729, 29752, 30767, 31772, 32768, + + 33753, 34728, 35693, 36647, 37589, 38521, 39440, 40347, 41243, 42125, + 42995, 43851, 44695, 45524, 46340, 47142, 47929, 48702, 49460, 50203, + 50930, 51642, 52339, 53019, 53683, 54331, 54962, 55577, 56174, 56755, + + 57318, 57864, 58392, 58902, 59395, 59869, 60325, 60763, 61182, 61583, + 61965, 62327, 62671, 62996, 63302, 63588, 63855, 64103, 64331, 64539, + 64728, 64897, 65047, 65176, 65286, 65375, 65445, 65495, 65525, 65535, + }; + +// 91 bytes +uint8_t isinTable8[] = { + 0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, + 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, + 91, 96, 100, 104, 108, 112, 116, 120, 124, 128, + + 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, + 167, 171, 174, 177, 180, 183, 186, 190, 192, 195, + 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, + + 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, + 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 253, 254, 254, 254, 255, 255, 255, 255, + }; + + +float isin(long x) +{ + boolean pos = true; // positive - keeps an eye on the sign. + if (x < 0) + { + x = -x; + pos = !pos; + } + if (x >= 360) x %= 360; + if (x > 180) + { + x -= 180; + pos = !pos; + } + if (x > 90) x = 180 - x; +// if (pos) return isinTable8[x] * 0.003921568627; // = /255.0 +// return isinTable8[x] * -0.003921568627 ; + if (pos) return isinTable16[x] * 0.0000152590219; // = /65535.0 + return isinTable16[x] * -0.0000152590219 ; +} + +float icos(long x) +{ + return isin(x+90); +} + +float itan(long x) +{ + return isin(x) / icos(x); +} + +float fsin(float d) +{ + float a = isin(d); + float b = isin(d+1); + return a + (d-int(d)) * (b-a); +} + +#endif diff --git a/Arduino/SelfomatController/FlashingState.cpp b/Arduino/SelfomatController/FlashingState.cpp new file mode 100644 index 0000000..0f9b9c1 --- /dev/null +++ b/Arduino/SelfomatController/FlashingState.cpp @@ -0,0 +1,55 @@ +#include "FlashingState.h" +#include "IdleState.h" + +FlashingState FlashingState::INSTANCE; + +bool FlashingState::processCommand(const uint8_t* buffer, size_t size) { + // Handle '.' since it's the only way to exit + if(size == 1 && buffer[0] == '.') { + shouldExit = true; + return true; + } + // Handle 'f' since our gui will spam until it hears from us + if(size == 1 && buffer[0] == 'f') { + sendCommand('F'); + } + // Nothing else + return false; +} + +void FlashingState::animationStep(unsigned long dt) { + + // Flash 10x per second + int on = (timeInState() / 150) & 0x01; + + for(int j = 0; j < ring.numPixels(); j++) { + if(on) { + ring.setPixelColor(j, 255, 0, 0); + } else { + ring.setPixelColor(j, 0, 0, 0); + } + } + ring.show(); +} + +BaseState* FlashingState::logicStep() { + if(shouldExit) { + sendCommand('a'); + return &IdleState::INSTANCE; + } + return this; +} + +void FlashingState::enter() { + BaseState::enter(); + shouldExit = false; +} + +void FlashingState::exit() { + +} + +bool FlashingState::needsHeartbeat() { + // Plz no + return false; +} diff --git a/Arduino/SelfomatController/FlashingState.h b/Arduino/SelfomatController/FlashingState.h new file mode 100644 index 0000000..649a8eb --- /dev/null +++ b/Arduino/SelfomatController/FlashingState.h @@ -0,0 +1,44 @@ +#ifndef FLASHING_STATE_H +#define FLASHING_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class FlashingState : public BaseState { +private: + uint8_t frame; + float b; + bool shouldExit; + bool exitAnimationDone; +public: + static FlashingState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/IdleState.cpp b/Arduino/SelfomatController/IdleState.cpp new file mode 100644 index 0000000..83f5ff5 --- /dev/null +++ b/Arduino/SelfomatController/IdleState.cpp @@ -0,0 +1,49 @@ +#include "IdleState.h" +#include "CountDownState.h" +#include "FastMath.h" + +IdleState IdleState::INSTANCE; + +bool IdleState::processCommand(const uint8_t* buffer, size_t size) { + if(BaseState::processCommand(buffer, size)) + return true; + if(size == 1 && buffer[0] == 't') { + externalTrigger = true; + } +} + +void IdleState::animationStep(unsigned long dt) { + float sinx = isin(timeInState()>>4); + float brightness = sinx*sinx; + uint8_t g = brightness * 255.0f; + for(int i = 0; i < ring.numPixels(); i++) { + ring.setPixelColor(i, 0, g, g >> 2); + } + ring.show(); +} + +BaseState* IdleState::logicStep() { + BaseState* parentStep = BaseState::logicStep(); + if(parentStep) + return parentStep; + + if(digitalRead(PIN_BUTTON) == LOW || externalTrigger) { + return &CountDownState::INSTANCE; + } + + return this; +} + +void IdleState::enter() { + BaseState::enter(); + externalTrigger = false; + green = 0; +} + +void IdleState::exit() { + +} + +bool IdleState::needsHeartbeat() { + return !heartbeatDeactivated; +} diff --git a/Arduino/SelfomatController/IdleState.h b/Arduino/SelfomatController/IdleState.h new file mode 100644 index 0000000..f076f40 --- /dev/null +++ b/Arduino/SelfomatController/IdleState.h @@ -0,0 +1,42 @@ +#ifndef IDLE_STATE_H +#define IDLE_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class IdleState : public BaseState { +private: + int16_t green; + bool externalTrigger; +public: + static IdleState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/OffState.cpp b/Arduino/SelfomatController/OffState.cpp new file mode 100644 index 0000000..f1338e7 --- /dev/null +++ b/Arduino/SelfomatController/OffState.cpp @@ -0,0 +1,66 @@ +#include "OffState.h" + +OffState OffState::INSTANCE; + +bool OffState::processCommand(const uint8_t* buffer, size_t size) { + // We drop serial commands in this state + return false; +} +void OffState::animationStep(unsigned long dt) { + // We have no animation in this state +} + +BaseState* OffState::logicStep() { + allowExitState |= timeInState() > 3000; + + if (!allowExitState) + return this; + + if (digitalRead(PIN_SWITCH) == LOW) { + // The switch is on and we're allowed to exit the off state->do it + return &BootingState::INSTANCE; + } + return this; +} + +void OffState::enter() { + BaseState::enter(); + + // read settings + readSettings(); + + allowExitState = false; + + + blink(3); + // Disable the ring + ring.setPin(PIN_LED_OFF); + digitalWrite(PIN_LED, LOW); + + // power off the system and level shifter + digitalWrite(PIN_LEVEL_SHIFTER_OE, LOW); + digitalWrite(PIN_ON, LOW); +} + +void OffState::exit() { + // read settings + readSettings(); + heartbeatDeactivated = false; + // If we exit the off state, we need to power the system and level shifter + digitalWrite(PIN_ON, HIGH); + digitalWrite(PIN_LEVEL_SHIFTER_OE, HIGH); + + + // Setup the ring + ring.setPin(PIN_LED); + ring.begin(); + ring.clear(); + ring.show(); + + blink(2); +} + +bool OffState::needsHeartbeat() { + // Obviously + return false; +} diff --git a/Arduino/SelfomatController/OffState.h b/Arduino/SelfomatController/OffState.h new file mode 100644 index 0000000..5ba7655 --- /dev/null +++ b/Arduino/SelfomatController/OffState.h @@ -0,0 +1,42 @@ +#ifndef OFF_STATE_H +#define OFF_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" +#include "BootingState.h" + +class OffState: public BaseState { + +private: + // Initially we're allowed to exit the state + bool allowExitState; +public: + static OffState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/PacketSerial.h b/Arduino/SelfomatController/PacketSerial.h new file mode 100644 index 0000000..e4e6232 --- /dev/null +++ b/Arduino/SelfomatController/PacketSerial.h @@ -0,0 +1,350 @@ +// +// Copyright (c) 2013 Christopher Baker +// +// SPDX-License-Identifier: MIT +// + + +#pragma once + + +#include +#include "Encoding/COBS.h" +#include "Encoding/SLIP.h" + + +/// \brief A template class enabling packet-based Serial communication. +/// +/// Typically one of the typedefined versions are used, for example, +/// `COBSPacketSerial` or `SLIPPacketSerial`. +/// +/// The template parameters allow the user to define their own packet encoder / +/// decoder, custom packet marker and receive buffer size. +/// +/// \tparam EncoderType The static packet encoder class name. +/// \tparam PacketMarker The byte value used to mark the packet boundary. +/// \tparam BufferSize The number of bytes allocated for the receive buffer. +template +class PacketSerial_ +{ +public: + /// \brief A typedef describing the packet handler method. + /// + /// The packet handler method usually has the form: + /// + /// void onPacketReceived(const uint8_t* buffer, size_t size); + /// + /// where buffer is a pointer to the incoming buffer array, and size is the + /// number of bytes in the incoming buffer. + typedef void (*PacketHandlerFunction)(const uint8_t* buffer, size_t size); + + /// \brief A typedef describing the packet handler method. + /// + /// The packet handler method usually has the form: + /// + /// void onPacketReceived(void* sender, const uint8_t* buffer, size_t size); + /// + /// where sender is a pointer to the PacketSerial_ instance that recieved + /// the buffer, buffer is a pointer to the incoming buffer array, and size + /// is the number of bytes in the incoming buffer. + typedef void (*PacketHandlerFunctionWithSender)(const void* sender, const uint8_t* buffer, size_t size); + + /// \brief Construct a default PacketSerial_ device. + PacketSerial_(): + _receiveBufferIndex(0), + _stream(nullptr), + _onPacketFunction(nullptr), + _onPacketFunctionWithSender(nullptr) + { + } + + /// \brief Destroy the PacketSerial_ device. + ~PacketSerial_() + { + } + + /// \brief Begin a default serial connection with the given speed. + /// + /// The default Serial port `Serial` and default config `SERIAL_8N1` will be + /// used. For example: + /// + /// PacketSerial myPacketSerial; + /// + /// void setup() + /// { + /// myPacketSerial.begin(9600); + /// } + /// + /// This is a convenience method. For more complex Serial port + /// configurations, use the `setStream()` function to set an arbitrary + /// Arduino Stream. + /// + /// \param speed The serial data transmission speed in bits / second (baud). + /// \sa https://www.arduino.cc/en/Serial/Begin + void begin(unsigned long speed) + { + Serial.begin(speed); + #if ARDUINO >= 100 && !defined(CORE_TEENSY) + while (!Serial) {;} + #endif + setStream(&Serial); + } + + /// \brief Deprecated. Use setStream() to configure a non-default port. + /// \param speed The serial data transmission speed in bits / second (baud). + /// \param port The Serial port number (e.g. 0 is Serial, 1 is Serial1). + /// \deprecated Use setStream() to configure a non-default port. + void begin(unsigned long speed, size_t port) __attribute__ ((deprecated)) + { + switch(port) + { + #if defined(UBRR1H) + case 1: + Serial1.begin(speed); + #if ARDUINO >= 100 && !defined(CORE_TEENSY) + while (!Serial1) {;} + #endif + setStream(&Serial1); + break; + #endif + #if defined(UBRR2H) + case 2: + Serial2.begin(speed); + #if ARDUINO >= 100 && !defined(CORE_TEENSY) + while (!Serial1) {;} + #endif + setStream(&Serial2); + break; + #endif + #if defined(UBRR3H) + case 3: + Serial3.begin(speed); + #if ARDUINO >= 100 && !defined(CORE_TEENSY) + while (!Serial3) {;} + #endif + setStream(&Serial3); + break; + #endif + default: + begin(speed); + } + } + + /// \brief Deprecated. Use setStream() to configure a non-default port. + /// \param stream A pointer to an Arduino `Stream`. + /// \deprecated Use setStream() to configure a non-default port. + void begin(Stream* stream) __attribute__ ((deprecated)) + { + _stream = stream; + } + + /// \brief Attach PacketSerial to an existing Arduino `Stream`. + /// + /// This `Stream` could be a standard `Serial` `Stream` with a non-default + /// configuration such as: + /// + /// PacketSerial myPacketSerial; + /// + /// void setup() + /// { + /// Serial.begin(300, SERIAL_7N1); + /// myPacketSerial.setStream(&Serial); + /// } + /// + /// Or it might be a `SoftwareSerial` `Stream` such as: + /// + /// PacketSerial myPacketSerial; + /// SoftwareSerial mySoftwareSerial(10, 11); + /// + /// void setup() + /// { + /// mySoftwareSerial.begin(38400); + /// myPacketSerial.setStream(&mySoftwareSerial); + /// } + /// + /// Any class that implements the `Stream` interface should work, which + /// includes some network objects. + /// + /// \param stream A pointer to an Arduino `Stream`. + void setStream(Stream* stream) + { + _stream = stream; + } + + /// \brief The update function services the serial connection. + /// + /// This must be called often, ideally once per `loop()`, e.g.: + /// + /// void loop() + /// { + /// // Other program code. + /// + /// myPacketSerial.update(); + /// } + /// + void update() + { + if (_stream == nullptr) return; + + while (_stream->available() > 0) + { + uint8_t data = _stream->read(); + + if (data == PacketMarker) + { + if (_onPacketFunction || _onPacketFunctionWithSender) + { + uint8_t _decodeBuffer[_receiveBufferIndex]; + + // BOOTLOADER DETECTION!!! + size_t numDecoded; + if(_receiveBufferIndex == 1 && _receiveBuffer[0] == '0') { + numDecoded = 1; + _decodeBuffer[0] = '0'; + } else { + numDecoded = EncoderType::decode(_receiveBuffer, + _receiveBufferIndex, + _decodeBuffer); + } + + if (_onPacketFunction) + { + _onPacketFunction(_decodeBuffer, numDecoded); + } + else if (_onPacketFunctionWithSender) + { + _onPacketFunctionWithSender(this, _decodeBuffer, numDecoded); + } + } + + _receiveBufferIndex = 0; + } + else + { + if ((_receiveBufferIndex + 1) < BufferSize) + { + _receiveBuffer[_receiveBufferIndex++] = data; + } + else + { + // Error, buffer overflow if we write. + } + } + } + } + + /// \brief Set a packet of data. + /// + /// This function will encode and send an arbitrary packet of data. After + /// sending, it will send the specified `PacketMarker` defined in the + /// template parameters. + /// + /// // Make an array. + /// uint8_t myPacket[2] = { 255, 10 }; + /// + /// // Send the array. + /// myPacketSerial.send(myPacket, 2); + /// + /// \param buffer A pointer to a data buffer. + /// \param size The number of bytes in the data buffer. + void send(const uint8_t* buffer, size_t size) const + { + if(_stream == nullptr || buffer == nullptr || size == 0) return; + + uint8_t _encodeBuffer[EncoderType::getEncodedBufferSize(size)]; + + size_t numEncoded = EncoderType::encode(buffer, + size, + _encodeBuffer); + + _stream->write(_encodeBuffer, numEncoded); + _stream->write(PacketMarker); + } + + /// \brief Set the function that will receive decoded packets. + /// + /// This function will be called when data is read from the serial stream + /// connection and a packet is decoded. The decoded packet will be passed + /// to the packet handler. The packet handler must have the form: + /// + /// The packet handler method usually has the form: + /// + /// void onPacketReceived(const uint8_t* buffer, size_t size); + /// + /// The packet handler would then be registered like this: + /// + /// myPacketSerial.setPacketHandler(&onPacketReceived); + /// + /// Setting a packet handler will remove all other packet handlers. + /// + /// \param onPacketFunction A pointer to the packet handler function. + void setPacketHandler(PacketHandlerFunction onPacketFunction) + { + _onPacketFunction = onPacketFunction; + _onPacketFunctionWithSender = nullptr; + } + + /// \brief Set the function that will receive decoded packets. + /// + /// This function will be called when data is read from the serial stream + /// connection and a packet is decoded. The decoded packet will be passed + /// to the packet handler. The packet handler must have the form: + /// + /// The packet handler method usually has the form: + /// + /// void onPacketReceived(const void* sender, const uint8_t* buffer, size_t size); + /// + /// To determine the sender, compare the pointer to the known possible + /// PacketSerial senders. + /// + /// void onPacketReceived(void* sender, const uint8_t* buffer, size_t size) + /// { + /// if (sender == &myPacketSerial) + /// { + /// // Do something with the packet from myPacketSerial. + /// } + /// else if (sender == &myOtherPacketSerial) + /// { + /// // Do something with the packet from myOtherPacketSerial. + /// } + /// } + /// + /// The packet handler would then be registered like this: + /// + /// myPacketSerial.setPacketHandler(&onPacketReceived); + /// + /// Setting a packet handler will remove all other packet handlers. + /// + /// \param onPacketFunctionWithSender A pointer to the packet handler function. + void setPacketHandler(PacketHandlerFunctionWithSender onPacketFunctionWithSender) + { + _onPacketFunction = nullptr; + _onPacketFunctionWithSender = onPacketFunctionWithSender; + } + +private: + PacketSerial_(const PacketSerial_&); + PacketSerial_& operator = (const PacketSerial_&); + + uint8_t _receiveBuffer[BufferSize]; + size_t _receiveBufferIndex = 0; + + Stream* _stream = nullptr; + + PacketHandlerFunction _onPacketFunction = nullptr; + PacketHandlerFunctionWithSender _onPacketFunctionWithSender = nullptr; +}; + + +/// \brief A typedef for the default COBS PacketSerial class. +typedef PacketSerial_ PacketSerial; + +/// \brief A typedef for a PacketSerial type with COBS encoding. +typedef PacketSerial_ COBSPacketSerial; + +/// \brief A typedef for a PacketSerial type with COBS encoding. +typedef PacketSerial_ COBSSpacePacketSerial; + + +/// \brief A typedef for a PacketSerial type with SLIP encoding. +typedef PacketSerial_ SLIPPacketSerial; diff --git a/Arduino/SelfomatController/PrintingState.cpp b/Arduino/SelfomatController/PrintingState.cpp new file mode 100644 index 0000000..d57ce70 --- /dev/null +++ b/Arduino/SelfomatController/PrintingState.cpp @@ -0,0 +1,72 @@ +#include "PrintingState.h" +#include "IdleState.h" + +PrintingState PrintingState::INSTANCE; + +bool PrintingState::processCommand(const uint8_t* buffer, size_t size) { + // Process base commands. No fancy extras needed + if(BaseState::processCommand(buffer, size)) + return true; + + if(size == 1 && buffer[0] == 'k') { + shouldExit = true; + } +} + +void PrintingState::animationStep(unsigned long dt) { + // Fade + if (shouldExit || cancelSent) { + if (b > 0.0) { + b -= min(b, 0.025); + } else { + exitAnimationDone = true; + } + } else { + if (b < 1.0) { + b += min(1-b, 0.01); + } + } + + + float angleOffset = timeInState()/300.0f; + float anglePerLed = (2.0 * PI) / ring.numPixels(); + for(int j = 0; j < ring.numPixels(); j++) { + float angle = (float)j * anglePerLed + angleOffset; + float sin_x = sin(angle); + uint8_t brightness = sin_x*sin_x * 255.0f * b; + ring.setPixelColor(j, 0, brightness, brightness >> 2); + } + ring.show(); +} + +BaseState* PrintingState::logicStep() { + BaseState *parentState = BaseState::logicStep(); + if(parentState) + return parentState; + + if(!cancelSent && digitalRead(PIN_BUTTON) == LOW) { + cancelSent = true; + sendCommand('c'); + } + + if(timeInState() > 30000 || (shouldExit && exitAnimationDone)) { + return &IdleState::INSTANCE; + } + return this; +} + +void PrintingState::enter() { + BaseState::enter(); + cancelSent = false; + b = 0; + frame = 0; + exitAnimationDone = shouldExit = false; +} + +void PrintingState::exit() { + +} + +bool PrintingState::needsHeartbeat() { + return !heartbeatDeactivated; +} diff --git a/Arduino/SelfomatController/PrintingState.h b/Arduino/SelfomatController/PrintingState.h new file mode 100644 index 0000000..f22ea23 --- /dev/null +++ b/Arduino/SelfomatController/PrintingState.h @@ -0,0 +1,45 @@ +#ifndef PRINTING_STATE_H +#define PRINTING_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class PrintingState : public BaseState { +private: + uint8_t frame; + float b; + bool shouldExit; + bool exitAnimationDone; + bool cancelSent; +public: + static PrintingState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/SelfomatController.ino b/Arduino/SelfomatController/SelfomatController.ino new file mode 100644 index 0000000..a51e350 --- /dev/null +++ b/Arduino/SelfomatController/SelfomatController.ino @@ -0,0 +1,131 @@ +/* + * Needed Libraries: + * Adafruit NeoPixel by Adafruit + * PinChangeInterrupt by NicoHood + */ + + +#include +#include "globals.h" +#include "FastCRC.h" +#include "State.h" +#include "OffState.h" +#include "IdleState.h" +#include "BusyState.h" + + +/* + * State Machine + */ +BaseState *currentState = 0; +unsigned long lastAnimationStep = 0; + +void goToState(BaseState *nextState) { + if(nextState == currentState) + return; + if(currentState) { + currentState->exit(); + } + currentState=nextState; + if(nextState) { + nextState->enter(); + } +} + + +void onPacketReceived(const uint8_t* buffer, size_t size) { + // Check, if we need to bootload. If so, do it. No state needed + if(size == 1) { + switch(buffer[0]) { + case '0': { + typedef void (*do_reboot_t)(void); + const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND - 511) >> 1); + cli(); MCUSR = TCCR0A = TCCR1A = TCCR2A = 0; // make sure interrupts are off and timers are reset. + do_reboot(); + } + return; + case 'i': { + // Identify yourself + Serial.write('b'); + Serial.flush(); + } + return; + case '.': { + // Reset our software watchdog + lastHeartbeat = millis(); + // no return here, we want it to propagate to the other states + break; + } + break; + default: + break; + } + } + if(currentState) { + currentState->processCommand(buffer, size); + } +} + +void setup() { + // Reset and disable Watchdog + // NEVER EVER REMOVE THE FOLLOWING 2 LINES!!!! + MCUSR = 0; + wdt_disable(); + + // Setup Pins + pinMode(PIN_STATUS, OUTPUT); + digitalWrite(PIN_STATUS, LOW); + + + + pinMode(PIN_BUTTON, INPUT); + digitalWrite(PIN_BUTTON, HIGH); + pinMode(PIN_SWITCH, INPUT); + digitalWrite(PIN_SWITCH, HIGH); + pinMode(PIN_FLASH_CAM_TRIGGER, INPUT); + // pullups + digitalWrite(PIN_FLASH_CAM_TRIGGER, HIGH); + + pinMode(PIN_FLASH_ON, OUTPUT); + // flash off by default + digitalWrite(PIN_FLASH_ON, LOW); + + pinMode(PIN_ON, OUTPUT); + pinMode(PIN_LEVEL_SHIFTER_OE, OUTPUT); + + + packetSerial.begin(38400); + packetSerial.setPacketHandler(&onPacketReceived); + + // If the switch is on, turn on instantly BUT ONLY THIS FIRST TIME + if(digitalRead(PIN_SWITCH) == LOW) { + // We want to call exit function but not enter function + currentState = &OffState::INSTANCE; + goToState(&BootingState::INSTANCE); + } else { + goToState(&OffState::INSTANCE); + } +} + +void loop() { + bool checkHeartbeat = currentState == 0 || currentState->needsHeartbeat(); + + if(checkHeartbeat && millis() - lastHeartbeat > 15000) { + // Turn off if heartbeat was not sent + goToState(&OffState::INSTANCE); + return; + } + + if(currentState) { + BaseState *nextState = currentState->logicStep(); + unsigned long dt = millis() - lastAnimationStep; + if(dt > 33) { + packetSerial.update(); + lastAnimationStep = millis(); + // approx 30fps + currentState->animationStep(dt); + } + goToState(nextState); + } + packetSerial.update(); +} diff --git a/Arduino/SelfomatController/ShutDownState.cpp b/Arduino/SelfomatController/ShutDownState.cpp new file mode 100644 index 0000000..8fa66a2 --- /dev/null +++ b/Arduino/SelfomatController/ShutDownState.cpp @@ -0,0 +1,61 @@ +#include "ShutDownState.h" +#include "OffState.h" + +ShutDownState ShutDownState::INSTANCE; + +bool ShutDownState::processCommand(const uint8_t* buffer, size_t size) { + return false; +} + +void ShutDownState::animationStep(unsigned long dt) { + + // Fade + if (shouldExit) { + if (b > 0) { + b-=min(b,4); + } else { + exitAnimationDone = true; + } + } else { + if (b < 255) { + b+=min(4, 255-b); + } + } + + // Animate + for (int i = 0; i < ring.numPixels(); i++) { + byte diff = (i - frame) % ring.numPixels(); + byte color = (b / ring.numPixels() * diff); + ring.setPixelColor(i, color, 0, 0); + } + ring.show(); + + // Skip to next frame + frame++; +} + +BaseState* ShutDownState::logicStep() { + // We never exit. This state will be exited using the heartbeat timeout + return this; +} + +void ShutDownState::enter() { + BaseState::enter(); + writeSettings(); + b = 0; + frame = 0; + exitAnimationDone = shouldExit = false; + sendCommand('d'); + + // Shutdown state, enable heartbeat and reset. We'll shut off as soon as no heartbeats arrive + timeout + lastHeartbeat = millis(); +} + +void ShutDownState::exit() { + +} + +bool ShutDownState::needsHeartbeat() { + // yes + return true; +} diff --git a/Arduino/SelfomatController/ShutDownState.h b/Arduino/SelfomatController/ShutDownState.h new file mode 100644 index 0000000..bcf775f --- /dev/null +++ b/Arduino/SelfomatController/ShutDownState.h @@ -0,0 +1,44 @@ +#ifndef SHUT_DOWN_STATE_H +#define SHUT_DOWN_STATE_H + +#include "State.h" +#include "globals.h" +#include "Arduino.h" + +class ShutDownState: public BaseState { +private: + uint32_t frame = 0; + int b = 0; + bool shouldExit; + bool exitAnimationDone; +public: + static ShutDownState INSTANCE; + /** + * Handle a serial command. + * @param buffer: the command buffer + * @param size: buffer length + * + * @returns: true, if the command was handled + */ + virtual bool processCommand(const uint8_t* buffer, size_t size); + virtual void animationStep(unsigned long dt); + + /** + * Do some polling logic + * @returns the pointer to the next state (can return itself) + */ + virtual BaseState* logicStep(); + /** + * Called ONCE on state enter + */ + virtual void enter(); + + /** + * Called ONCE before state exits + */ + virtual void exit(); + + virtual bool needsHeartbeat(); +}; + +#endif diff --git a/Arduino/SelfomatController/State.cpp b/Arduino/SelfomatController/State.cpp new file mode 100644 index 0000000..4bbfc76 --- /dev/null +++ b/Arduino/SelfomatController/State.cpp @@ -0,0 +1,212 @@ +#include "State.h" +#include "ShutDownState.h" +#include "AgreementState.h" +#include "FlashingState.h" + +BaseState* BaseState::forcedNextState = 0; + +BaseState* BaseState::logicStep() { + if (digitalRead(PIN_SWITCH) == HIGH) { + // The switch is off, we want to get to off + return &ShutDownState::INSTANCE; + } + + if(forcedNextState) { + BaseState *tmp = forcedNextState; + forcedNextState = 0; + return tmp; + } + + // else, we do not care + return 0; +}; + +void BaseState::sendCurrentSettings() { + size_t data_size = sizeof(settings)+1; + uint8_t data[data_size]; + data[0] = '$'; + memcpy(data+1, &settings, data_size-1); + packetSerial.send(data, data_size); + Serial.flush(); +} + +bool BaseState::processCommand(const uint8_t* buffer, size_t size) { + if (size == 0) + return false; + unsigned char c = buffer[0]; + switch (c) { + case '#': + // TODO: reimplement here + return true; + case 'a': + forcedNextState = &AgreementState::INSTANCE; + return true; + break; + case '$': + if(size != sizeof(settings)+1) { + // we have received the wrong amount of bytes. Ignore this message and throw an error + sendCommand("E1",2); + return true; + } else { + // We know the buffer has the correct size, cast it + struct settings *received_settings = (struct settings*)(buffer+1); + + // Check the CRC + uint16_t crc = CRC16.ccitt((const uint8_t *) received_settings, sizeof(struct settings)-2); + if(crc != received_settings->crcChecksum) { + // CRC error, notify receiver and ignore + sendCommand("E2", 2); + return true; + } + + // check if settings are valid + if(!checkSettings(received_settings)) { + sendCommand("E3", 2); + return true; + } + + // CRC is OK. Set dirty by comparing the new settings to the old ones and overwrite the settings if changed. + if(0 == memcmp(&settings, received_settings, sizeof(struct settings))) { + // Settings are the same, don't do anything. + } else { + // We have new settings. Set the dirty flag and overwrite settings + settingsDirty = true; + settings = *received_settings; + updateSettingDependencies(); + } + + // Send a k to notify setting reception success + sendCommand('k'); + } + return true; + break; + case 'f': + forcedNextState = &FlashingState::INSTANCE; + sendCommand('F'); + return true; + break; + case '!': + if(size == 2) { + heartbeatDeactivated = buffer[1] == 0; + lastHeartbeat = millis(); + } + break; + case '?': + sendCurrentSettings(); + break; + case '<': + if(settings.ledOffset == 0) { + settings.ledOffset = settings.ledCount; + } else { + settings.ledOffset--; + } + settings.crcChecksum = CRC16.ccitt((const uint8_t *) &settings, sizeof(settings)-2); + settingsDirty = true; + sendCurrentSettings(); + showCenterLed(400); + break; + case '>': + settings.ledOffset = (settings.ledOffset+1)%settings.ledCount; + settings.crcChecksum = CRC16.ccitt((const uint8_t *) &settings, sizeof(settings)-2); + settingsDirty = true; + sendCurrentSettings(); + showCenterLed(400); + break; + default: + return false; + } + return true; +}; + +void BaseState::blink(uint8_t count) { + while (count-- > 0) { + digitalWrite(PIN_STATUS, HIGH); + delay(100); + digitalWrite(PIN_STATUS, LOW); + delay(100); + } +} + +void BaseState::readSettings() { + EEPROM.get(0, settings); + settingsDirty = false; + + // Check, if CRC is OK. + uint16_t crc = CRC16.ccitt((const uint8_t *) &settings, sizeof(settings) - 2); + + if (crc == settings.crcChecksum) { + updateSettingDependencies(); + return; + } + + // load defaults + settings = default_settings; + // calculate crc for default settings + settings.crcChecksum = CRC16.ccitt((const uint8_t *) &settings, sizeof(settings) - 2); + updateSettingDependencies(); +} + +void BaseState::writeSettings() { + if(!settingsDirty) + return; + + settings.crcChecksum = CRC16.ccitt((const uint8_t *) &settings, sizeof(settings)-2); + EEPROM.put(0, settings); + settingsDirty = false; +} + +// Updates the dependencies (e.g. ring) using the new settings +void BaseState::updateSettingDependencies() { + ring.updateLength(settings.ledCount); + ring.updateType(supportedPixels[settings.ledTypeIndex]); + ring.setBrightness(settings.maxLedBrightness); +} + +void BaseState::enter() { + millisEnteredState = millis(); +} + +unsigned long BaseState::timeInState() { + return millis() - millisEnteredState; +} + +void BaseState::sendCommand(const char command) { + sendCommand(&command, 1); +} + +void BaseState::sendCommand(const char *command, uint8_t length) { + packetSerial.send((const uint8_t*)command, length); + Serial.flush(); +} + +bool BaseState::checkSettings(struct settings* settings_ptr) { + if(settings_ptr->ledTypeIndex >= PIXEL_TYPES) + return false; + + if(settings_ptr->ledCount > 32) + return false; + + if(settings_ptr->countDownMillis > 15000) + return false; + + if(settings_ptr->flashDurationMicros > 1000000) + return false; + return true; +} + + +void BaseState::showCenterLed(uint16_t duration) { + for(int8_t i=0; i +#include "FastCRC.h" +#include "PacketSerial.h" + +/* + * PIN Defines + */ +#define PIN_LED 4 +#define PIN_LED_OFF 9 + +#define PIN_STATUS 20 + +// DO NOT CHANGE!!! WE HAVE DIRECT HARDWARE ACCESS ON THIS PIN!!!! +#define PIN_FLASH_ON 11 +#define PIN_FLASH_CAM_TRIGGER 7 + +#define PIN_BUTTON 2 +#define PIN_SWITCH 3 +#define PIN_ON 8 +#define PIN_LEVEL_SHIFTER_OE 19 + +#define PIXEL_TYPES 2 +extern neoPixelType supportedPixels[PIXEL_TYPES]; + + + + +/** + * Setting Defines + */ + +#pragma pack(push, 1) + +struct settings { + uint8_t ledTypeIndex; + uint8_t ledCount; + uint8_t ledOffset; + uint16_t countDownMillis; + uint32_t flashDurationMicros; + uint8_t flashMode; + uint8_t maxLedBrightness; + uint16_t crcChecksum; +} __attribute__((packed)); + +extern struct settings settings; +extern struct settings default_settings; +extern bool settingsDirty; + +#pragma pack(pop) + +extern Adafruit_NeoPixel ring; +extern FastCRC16 CRC16; +extern COBSSpacePacketSerial packetSerial; + +extern unsigned long lastHeartbeat; +extern bool heartbeatDeactivated; + +#endif