diff --git a/src/RadioLib.h b/src/RadioLib.h index f4e690a7..b8a36385 100644 --- a/src/RadioLib.h +++ b/src/RadioLib.h @@ -110,6 +110,9 @@ #include "protocols/Print/Print.h" #include "protocols/BellModem/BellModem.h" +// utilities +#include "utils/CRC.h" + // only create Radio class when using RadioShield #if defined(RADIOLIB_RADIOSHIELD) diff --git a/src/utils/CRC.cpp b/src/utils/CRC.cpp new file mode 100644 index 00000000..5001a484 --- /dev/null +++ b/src/utils/CRC.cpp @@ -0,0 +1,39 @@ +#include "CRC.h" + +RadioLibCRC::RadioLibCRC(uint8_t size, uint32_t poly, uint32_t init, uint32_t out, bool refIn, bool refOut) { + this->size = size; + this->poly = poly; + this->init = init; + this->out = out; + this->refIn = refIn; + this->refOut = refOut; +} + +uint32_t RadioLibCRC::checksum(uint8_t* buff, size_t len) { + uint32_t crc = this->init; + for(size_t i = 0; i < len; i+=this->size/8) { + uint32_t window = 0; + for(uint8_t j = 0; j < this->size/8; j++) { + uint8_t inByte = buff[i + j]; + if(this->refIn) { + inByte = Module::reflect(inByte, 8); + } + window |= (inByte << ((this->size - 8) - 8*j)); + } + crc ^= window; + for(size_t k = 0; k < this->size; k++) { + if(crc & ((uint32_t)1 << (this->size - 1))) { + crc <<= (uint32_t)1; + crc ^= this->poly; + } else { + crc <<= (uint32_t)1; + } + } + } + crc ^= this->out; + if(this->refOut) { + crc = Module::reflect(crc, this->size); + } + crc &= (uint32_t)0xFFFFFFFF >> (32 - this->size); + return(crc); +} diff --git a/src/utils/CRC.h b/src/utils/CRC.h new file mode 100644 index 00000000..bf2998dd --- /dev/null +++ b/src/utils/CRC.h @@ -0,0 +1,71 @@ +#if !defined(_RADIOLIB_CRC_H) +#define _RADIOLIB_CRC_H + +#include "../TypeDef.h" +#include "../Module.h" +#if defined(RADIOLIB_BUILD_ARDUINO) +#include "../ArduinoHal.h" +#endif + +// CCITT CRC properties (used by AX.25) +#define RADIOLIB_CRC_CCITT_POLY (0x1021) +#define RADIOLIB_CRC_CCITT_INIT (0xFFFF) +#define RADIOLIB_CRC_CCITT_OUT (0xFFFF) + +/*! + \class AX25Frame + \brief Abstraction of AX.25 frame format. +*/ +class RadioLibCRC { + public: + /*! + \brief CRC size in bits. + */ + uint8_t size; + + /*! + \brief CRC polynomial. + */ + uint32_t poly; + + /*! + \brief Initial value. + */ + uint32_t init; + + /*! + \brief Final XOR value. + */ + uint32_t out; + + /*! + \brief Whether to reflect input bytes. + */ + bool refIn; + + /*! + \brief Whether to reflect the result. + */ + bool refOut; + + /*! + \brief Default constructor. + \param size CRC size in bits. + \param poly CRC polynomial. + \param init Initial value. + \param out Final XOR value. + \param refIn Whether to reflect input bytes. + \param refOut Whether to reflect the result. + */ + RadioLibCRC(uint8_t size, uint32_t poly, uint32_t init, uint32_t out, bool refIn, bool refOut); + + /*! + \brief Calcualte checksum of a buffer. + \param buff Buffer to calculate the checksum over. + \param len Size of the buffer in bytes. + \returns The resulting checksum. + */ + uint32_t checksum(uint8_t* buff, size_t len); +}; + +#endif