mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-16 07:16:30 +00:00
SML: CRC for binary SML (#23205)
* SML: CRC for binary SML parsing * switch algos * improve errormessage on buffer overflow * move crc variable to their own struct * Use Flag bit to disable CRC, auto-detect algorithm, data in own struct debug log * configure and enable/disable via special option "=soC,bufsz,mode", mode 16 autodetect. * fix 15 vs 0xF * remove benchmark code * fix typo in comment * Byteflip for CRC
This commit is contained in:
parent
c121dbcd4a
commit
4ed48feaa2
21
lib/lib_div/FastCRC/LICENCE.md
Normal file
21
lib/lib_div/FastCRC/LICENCE.md
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Frank
|
||||
|
||||
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.
|
56
lib/lib_div/FastCRC/README.md
Normal file
56
lib/lib_div/FastCRC/README.md
Normal file
@ -0,0 +1,56 @@
|
||||
FastCRC
|
||||
=======
|
||||
|
||||
Fast CRC Arduino library
|
||||
Up to 30 times faster than crc16.h (_avr_libc)
|
||||
|
||||
- uses the on-chip hardware for Teensy 3.0 / 3.1 / 3.2 / 3.5 / 3.6
|
||||
- uses fast table-algorithms for other chips
|
||||
|
||||
List of supported CRC calculations:
|
||||
-
|
||||
7 BIT:
|
||||
|
||||
CRC7
|
||||
(poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75)
|
||||
MultiMediaCard interface
|
||||
|
||||
|
||||
8 BIT:
|
||||
|
||||
SMBUS
|
||||
(poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4)
|
||||
|
||||
MAXIM
|
||||
(poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1)
|
||||
|
||||
|
||||
16 BIT:
|
||||
|
||||
KERMIT (Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT)
|
||||
(poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
|
||||
Attention: sometimes you'll find byteswapped presentation of result in other implementations)
|
||||
|
||||
CCITT-FALSE
|
||||
(poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1)
|
||||
|
||||
MCRF4XX
|
||||
(poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91)
|
||||
|
||||
MODBUS
|
||||
(poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37)
|
||||
|
||||
XMODEM (Alias ZMODEM, CRC-16/ACORN)
|
||||
(poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3)
|
||||
|
||||
X25 (Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B)
|
||||
(poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e)
|
||||
|
||||
|
||||
32 BIT:
|
||||
|
||||
CRC32, CRC-32/ADCCP, PKZIP, ETHERNET, 802.3
|
||||
(poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926)
|
||||
|
||||
CKSUM, CRC-32/POSIX
|
||||
(poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680)
|
59
lib/lib_div/FastCRC/keywords.txt
Normal file
59
lib/lib_div/FastCRC/keywords.txt
Normal file
@ -0,0 +1,59 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For FastCRC
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
FastCRC7 KEYWORD1
|
||||
FastCRC8 KEYWORD1
|
||||
FastCRC14 KEYWORD1
|
||||
FastCRC16 KEYWORD1
|
||||
FastCRC32 KEYWORD1
|
||||
CRC7 KEYWORD1
|
||||
CRC8 KEYWORD1
|
||||
CRC14 KEYWORD1
|
||||
CRC16 KEYWORD1
|
||||
CRC32 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
crc7 KEYWORD2
|
||||
crc7_upd KEYWORD2
|
||||
ccitt KEYWORD2
|
||||
ccitt_upd KEYWORD2
|
||||
kermit KEYWORD2
|
||||
kermit_upd KEYWORD2
|
||||
mcrf4xx KEYWORD2
|
||||
mcrf4xx_upd KEYWORD2
|
||||
modbus KEYWORD2
|
||||
modbus_upd KEYWORD2
|
||||
xmodem KEYWORD2
|
||||
xmodem_upd KEYWORD2
|
||||
x25 KEYWORD2
|
||||
x25_upd KEYWORD2
|
||||
update KEYWORD2
|
||||
update_upd KEYWORD2
|
||||
generic KEYWORD2
|
||||
crc32 KEYWORD2
|
||||
crc32_upd KEYWORD2
|
||||
cksum KEYWORD2
|
||||
cksum_upd KEYWORD2
|
||||
darc KEYWORD2
|
||||
darc_upd KEYWORD2
|
||||
gsm KEYWORD2
|
||||
gsm_upd KEYWORD2
|
||||
eloran KEYWORD2
|
||||
eloran_upd KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
CRC_FLAG_NOREFLECT LITERAL1
|
||||
CRC_FLAG_REFLECT LITERAL1
|
||||
CRC_FLAG_XOR LITERAL1
|
||||
CRC_FLAG_NOREFLECT_8 LITERAL1
|
||||
CRC_FLAG_REFLECT_SWAP LITERAL1
|
26
lib/lib_div/FastCRC/library.json
Normal file
26
lib/lib_div/FastCRC/library.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "FastCRC",
|
||||
"keywords": "CRC7, CRC8, CRC16, CRC32",
|
||||
"description": "Fast CRC routines for Arduino and PC (Teensy 3.x: CRC in hardware)",
|
||||
"exclude": [
|
||||
"examples",
|
||||
"examples_PC"
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/FrankBoesing/FastCRC"
|
||||
},
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Frank Bösing",
|
||||
"email": "f.boesing@gmx.de",
|
||||
"url": "https://github.com/FrankBoesing/FastCRC",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"version": "1.44",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
10
lib/lib_div/FastCRC/library.properties
Normal file
10
lib/lib_div/FastCRC/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=FastCRC
|
||||
version=1.44
|
||||
author=Frank Bösing
|
||||
maintainer=Frank Boesing<f.boesing@gmx.de>
|
||||
sentence=Fast CRC routines
|
||||
paragraph=
|
||||
category=Data Processing
|
||||
url=https://github.com/FrankBoesing/FastCRC
|
||||
architectures=*
|
||||
#dot_a_linkage=true
|
189
lib/lib_div/FastCRC/src/FastCRC.h
Normal file
189
lib/lib_div/FastCRC/src/FastCRC.h
Normal file
@ -0,0 +1,189 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 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:
|
||||
#if !defined(CRC_BIGTABLES)
|
||||
#define CRC_BIGTABLES 1
|
||||
#endif
|
||||
|
||||
#if !defined(FastCRC_h)
|
||||
#define FastCRC_h
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#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 size_t datalen); // (MultiMediaCard interface)
|
||||
uint8_t crc7_upd(const uint8_t *data, const size_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 size_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 size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 8-BIT CRC ===================
|
||||
|
||||
class FastCRC8
|
||||
{
|
||||
public:
|
||||
FastCRC8();
|
||||
uint8_t smbus(const uint8_t *data, const size_t datalen); // Alias CRC-8
|
||||
uint8_t maxim(const uint8_t *data, const size_t datalen); // Equivalent to _crc_ibutton_update() in crc16.h from avr_libc
|
||||
|
||||
uint8_t smbus_upd(const uint8_t *data, size_t datalen); // Call for subsequent calculations with previous seed.
|
||||
uint8_t maxim_upd(const uint8_t *data, size_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 size_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 size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 14-BIT CRC ===================
|
||||
|
||||
class FastCRC14
|
||||
{
|
||||
public:
|
||||
#if !CRC_SW //NO Software-implemenation so far
|
||||
FastCRC14();
|
||||
uint16_t darc(const uint8_t *data, const size_t datalen);
|
||||
uint16_t gsm(const uint8_t *data, const size_t datalen);
|
||||
uint16_t eloran(const uint8_t *data, const size_t datalen);
|
||||
uint16_t ft4(const uint8_t *data, const size_t datalen);
|
||||
|
||||
uint16_t darc_upd(const uint8_t *data, size_t len);
|
||||
uint16_t gsm_upd(const uint8_t *data, size_t len);
|
||||
uint16_t eloran_upd(const uint8_t *data, size_t len);
|
||||
uint16_t ft4_upd(const uint8_t *data, size_t len);
|
||||
#endif
|
||||
#if !CRC_SW
|
||||
uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_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 size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 16-BIT CRC ===================
|
||||
|
||||
class FastCRC16
|
||||
{
|
||||
public:
|
||||
FastCRC16();
|
||||
uint16_t ccitt(const uint8_t *data, const size_t datalen); // Alias "false CCITT"
|
||||
uint16_t mcrf4xx(const uint8_t *data,const size_t datalen); // Equivalent to _crc_ccitt_update() in crc16.h from avr_libc
|
||||
uint16_t kermit(const uint8_t *data, const size_t datalen); // Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
|
||||
uint16_t modbus(const uint8_t *data, const size_t datalen); // Equivalent to _crc_16_update() in crc16.h from avr_libc
|
||||
uint16_t xmodem(const uint8_t *data, const size_t datalen); // Alias ZMODEM, CRC-16/ACORN
|
||||
uint16_t x25(const uint8_t *data, const size_t datalen); // Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
|
||||
|
||||
uint16_t ccitt_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t mcrf4xx_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t kermit_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t modbus_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t xmodem_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t x25_upd(const uint8_t *data, size_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 size_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 size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 32-BIT CRC ===================
|
||||
|
||||
class FastCRC32
|
||||
{
|
||||
public:
|
||||
FastCRC32();
|
||||
uint32_t crc32(const uint8_t *data, const size_t datalen); // Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
|
||||
uint32_t cksum(const uint8_t *data, const size_t datalen); // Alias CRC-32/POSIX
|
||||
|
||||
uint32_t crc32_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint32_t cksum_upd(const uint8_t *data, size_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 size_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 size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
1596
lib/lib_div/FastCRC/src/FastCRC_tables.h
Normal file
1596
lib/lib_div/FastCRC/src/FastCRC_tables.h
Normal file
File diff suppressed because it is too large
Load Diff
567
lib/lib_div/FastCRC/src/FastCRChw.cpp
Normal file
567
lib/lib_div/FastCRC/src/FastCRChw.cpp
Normal file
@ -0,0 +1,567 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 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)
|
||||
//
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
#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 size_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 size_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<<CRC_CTRL_TOTR1))
|
||||
return rCRC->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 size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<(24 + 1); // Set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<(24 + 1)); // Write seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
|
||||
|
||||
|
||||
// ================= 8-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC8::FastCRC8(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
|
||||
/** SMBUS CRC
|
||||
* aka CRC-8
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
|
||||
return generic(0x07, 0, CRC_FLAG_NOREFLECT, 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(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
|
||||
return generic(0x31, 0, CRC_FLAG_REFLECT, 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 FastCRC8::update(const uint8_t *data, const size_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
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->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 size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<24; // Set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<24); // Write seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
|
||||
|
||||
|
||||
// ================= 14-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC14::FastCRC14(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CRC-14/DARC
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::darc(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d residue=0x0000
|
||||
return generic(0x0805, 0x0000, CRC_FLAG_REFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/GSM
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::gsm(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x202d init=0x0000 refin=false refout=false xorout=0x3fff check=0x30ae residue=0x031e
|
||||
return generic(0x202d, 0x0000, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/ELORAN
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::eloran(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x60b1 init=0x0000 refin=false refout=false xorout=0x0000 check=0x38d1
|
||||
return generic(0x60b1, 0x0, CRC_FLAG_NOREFLECT , data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/ft4 : TODO
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
/*
|
||||
uint16_t FastCRC14::ft4(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
|
||||
return generic(, , , data, datalen);
|
||||
}
|
||||
*/
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::update(const uint8_t *data, const size_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
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->CRC16;
|
||||
else
|
||||
return rCRC->CRC >> (32 - 14);
|
||||
}
|
||||
|
||||
/** generic function for all 14-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 FastCRC14::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom) << (32 - 14); // set polynom
|
||||
rCRC->CRC = ((uint32_t)seed << (32 - 14) ); // this is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint16_t FastCRC14::darc_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC14::gsm_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC14::eloran_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
//uint16_t FastCRC14::ft4(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
|
||||
|
||||
// ================= 16-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC16::FastCRC16(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CCITT
|
||||
* Alias "false CCITT"
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_NOREFLECT, 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(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT , 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(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
|
||||
return generic(0x8005, 0XFFFF, CRC_FLAG_REFLECT, 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(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
|
||||
// sometimes byteswapped presentation of result
|
||||
return generic(0x1021, 0x00, CRC_FLAG_REFLECT, 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(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
//width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
|
||||
return generic(0x1021, 0, CRC_FLAG_NOREFLECT, 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(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::update(const uint8_t *data, const size_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
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->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 size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<16; // set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<16); // this is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
|
||||
|
||||
|
||||
// ================= 32-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC32::FastCRC32(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CRC32
|
||||
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
|
||||
return generic(0x04C11DB7L, 0XFFFFFFFFL, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** CKSUM
|
||||
* Alias CRC-32/POSIX
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
|
||||
return generic(0x04C11DB7L, 0, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
//#pragma GCC diagnostic ignored "-Wpointer-arith"
|
||||
uint32_t FastCRC32::update(const uint8_t *data, const size_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
|
||||
}
|
||||
|
||||
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 size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = polynom; // Set polynom
|
||||
rCRC->CRC = seed; // This is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
#endif // #if defined(KINETISK)
|
541
lib/lib_div/FastCRC/src/FastCRCsw.cpp
Normal file
541
lib/lib_div/FastCRC/src/FastCRCsw.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 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.
|
||||
*/
|
||||
|
||||
//
|
||||
// Thanks to:
|
||||
// - Catalogue of parametrised CRC algorithms, CRC RevEng
|
||||
// http://reveng.sourceforge.net/crc-catalogue/
|
||||
//
|
||||
// - Danjel McGougan (CRC-Table-Generator)
|
||||
//
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#if !defined(KINETISK)
|
||||
|
||||
#if !defined(ARDUINO)
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned short *)(_addr); \
|
||||
})
|
||||
#define pgm_read_dword(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned long *)(_addr); \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "FastCRC.h"
|
||||
#include "FastCRC_tables.h"
|
||||
|
||||
|
||||
static inline
|
||||
uint32_t REV16( uint32_t value)
|
||||
{
|
||||
return (value >> 8) | ((value & 0xff) << 8);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t REV32( uint32_t value)
|
||||
{
|
||||
value = (value >> 16) | ((value & 0xffff) << 16);
|
||||
return ((value >> 8) & 0xff00ff) | ((value & 0xff00ff) << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ================= 7-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
FastCRC7::FastCRC7(){}
|
||||
|
||||
/** SMBUS CRC
|
||||
* aka CRC-8
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen)
|
||||
{
|
||||
uint8_t crc = seed;
|
||||
if (datalen) do {
|
||||
crc = pgm_read_byte(&crc_table_crc7[crc ^ *data]);
|
||||
data++;
|
||||
} while (--datalen);
|
||||
seed = crc;
|
||||
return crc >> 1;
|
||||
}
|
||||
|
||||
uint8_t FastCRC7::crc7(const uint8_t *data, const size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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, size_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 size_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)
|
@ -118,6 +118,10 @@
|
||||
#include "han_Parser.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SML_CRC
|
||||
#include "FastCRC.h"
|
||||
FastCRC16 FastCRC;
|
||||
#endif
|
||||
|
||||
#ifndef SML_TRX_BUFF_SIZE
|
||||
#define SML_TRX_BUFF_SIZE 1024
|
||||
@ -194,6 +198,11 @@ on esp8266 6 filters
|
||||
A:
|
||||
decryption flags (8 bits)
|
||||
|
||||
C:
|
||||
crc buffers and algorithm (available when compiled with USE_SML_CRC)
|
||||
a. crc buffer size (bytes), must hold one full file
|
||||
b. crc-algorithm: 0=x25, 1=ccitt, 15=autodetect
|
||||
e.g. 1,=soC,1024,15
|
||||
*/
|
||||
|
||||
//#define MODBUS_DEBUG
|
||||
@ -467,6 +476,20 @@ typedef union {
|
||||
#define SML_PREFIX_SIZE 8
|
||||
#endif
|
||||
|
||||
#ifdef USE_SML_CRC
|
||||
struct SML_CRC_DATA {
|
||||
uint8_t crcmode; //currently used mode
|
||||
uint8_t crcdetectstate; //current auto-detection state
|
||||
uint8_t *crcbuff; //buffer, only allocated on meter that have crc enabled
|
||||
uint16_t crcbuff_pos; //current buffer wiring position
|
||||
uint32_t crcfailcnt; //cnt bad-crc telegrams
|
||||
uint32_t crcfinecnt; //cnt good-crc telegrams
|
||||
uint32_t overflowcnt; //cnt good-crc telegrams
|
||||
sint8_t telestartpos; //-1=still searching, 0=found
|
||||
sint16_t teleendpos; //end of the telegram in the buffer or -1 when waiting for it
|
||||
};
|
||||
#endif // USE_SML_CRC
|
||||
|
||||
struct METER_DESC {
|
||||
int8_t srcpin;
|
||||
uint8_t type;
|
||||
@ -490,6 +513,10 @@ struct METER_DESC {
|
||||
uint16_t tout_ms;
|
||||
SO_FLAGS so_flags;
|
||||
char meter_id[METER_ID_SIZE];
|
||||
#ifdef USE_SML_CRC
|
||||
uint16_t so_sml_crc = 0;
|
||||
struct SML_CRC_DATA* sml_crc_data;
|
||||
#endif
|
||||
#ifdef USE_SML_SPECOPT
|
||||
uint32_t so_obis1;
|
||||
uint32_t so_obis2;
|
||||
@ -498,7 +525,6 @@ struct METER_DESC {
|
||||
uint8_t so_fcode2;
|
||||
uint8_t so_bpos2;
|
||||
#endif // USE_SML_SPECOPT
|
||||
|
||||
#ifdef ESP32
|
||||
#ifndef USE_ESP32_SW_SERIAL
|
||||
HardwareSerial *meter_ss;
|
||||
@ -557,6 +583,7 @@ struct METER_DESC {
|
||||
|
||||
|
||||
|
||||
|
||||
#define TCP_MODE_FLG 0x7f
|
||||
|
||||
// Meter flags
|
||||
@ -1413,6 +1440,36 @@ uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ) {
|
||||
return Crc;
|
||||
}
|
||||
|
||||
#ifdef USE_SML_CRC
|
||||
uint16_t calculateSMLbinCRC(const uint8_t *data, uint16_t length, uint8_t crcmode) {
|
||||
uint16_t res=0;
|
||||
switch (crcmode % 6) {
|
||||
case 0:
|
||||
res = FastCRC.x25(data, length);
|
||||
break;
|
||||
case 1:
|
||||
res = FastCRC.ccitt(data, length);
|
||||
break;
|
||||
case 2:
|
||||
res = FastCRC.kermit(data, length);
|
||||
break;
|
||||
case 3:
|
||||
res = FastCRC.modbus(data, length);
|
||||
break;
|
||||
case 4:
|
||||
res = FastCRC.xmodem(data, length);
|
||||
break;
|
||||
case 5:
|
||||
res = FastCRC.mcrf4xx(data, length);
|
||||
break;
|
||||
}
|
||||
if (crcmode>5) {
|
||||
res = (res >> 8) | (res << 8); // swap bytes
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
void sml_empty_receiver(uint32_t meters) {
|
||||
while (meter_desc[meters].meter_ss->available()) {
|
||||
meter_desc[meters].meter_ss->read();
|
||||
@ -1426,6 +1483,108 @@ void sml_shift_in(uint32_t meters, uint32_t shard) {
|
||||
|
||||
if (!mp->sbuff) return;
|
||||
|
||||
#ifdef USE_SML_CRC
|
||||
if ((mp->type=='s') && (mp->sml_crc_data) && (mp->so_sml_crc & 0x0fff)) {
|
||||
// New handling with CRC validation
|
||||
// Read data into the temporary buffer
|
||||
struct SML_CRC_DATA *cp = mp->sml_crc_data;
|
||||
if (cp->crcbuff_pos < (mp->so_sml_crc & 0x0fff)) {
|
||||
cp->crcbuff[cp->crcbuff_pos++] = mp->meter_ss->read();
|
||||
} else {
|
||||
// Buffer overflow, reset and log an error
|
||||
cp->overflowcnt++;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC buffer overflow, increase crc buffer size in your script modifying the line '1,soC=<buffer size>,<mode>'. Error occured %d times."),cp->overflowcnt);
|
||||
//Hexdump(&cp->crcbuff[0], cp->crcbuff_pos);
|
||||
if (cp->teleendpos==-1) {
|
||||
if (cp->telestartpos==-1) {
|
||||
AddLog(LOG_LEVEL_DEBUG, "SML: No start sequence was found.");
|
||||
} else {
|
||||
AddLog(LOG_LEVEL_DEBUG, "SML: Start sequence was found, but no stop sequence was found.");
|
||||
}
|
||||
}
|
||||
cp->telestartpos=-1;
|
||||
cp->teleendpos=-1;
|
||||
cp->crcbuff_pos = 0;
|
||||
}
|
||||
|
||||
// Check for start of message until it is found
|
||||
if (cp->telestartpos==-1) {
|
||||
//check start of buffer for start sequence
|
||||
if(cp->crcbuff_pos>=8) {
|
||||
if (memcmp(&cp->crcbuff[0], "\x1B\x1B\x1B\x1B\x01\x01\x01\x01", 8) == 0 ) {
|
||||
//found start sequence
|
||||
cp->telestartpos=0;
|
||||
} else {
|
||||
memmove(&cp->crcbuff[0], &cp->crcbuff[1], cp->crcbuff_pos-1);
|
||||
cp->crcbuff_pos--;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (cp->teleendpos==-1) {
|
||||
if(cp->crcbuff_pos>=16 && memcmp(&cp->crcbuff[cp->crcbuff_pos-8], "\x1B\x1B\x1B\x1B\x1A", 5) == 0 )
|
||||
{
|
||||
//found end sequence
|
||||
cp->teleendpos=cp->crcbuff_pos-1;
|
||||
//AddLog(LOG_LEVEL_INFO, PSTR("SML: Found stop sequence at %d length %d"),mp->teleendpos,len);
|
||||
//Validate CRC
|
||||
uint16_t extracted_crc = (cp->crcbuff[cp->crcbuff_pos - 1] << 8) | cp->crcbuff[cp->crcbuff_pos - 2];
|
||||
// Calculate the CRC for the data portion (excluding start, stop sequences, and CRC bytes)
|
||||
uint16_t len=cp->teleendpos + 1;
|
||||
//testing: fake some error for testing
|
||||
//if (random(0, 50) < 30) {cp->crcbuff[12]=99;}
|
||||
uint16_t calculated_crc = calculateSMLbinCRC(&cp->crcbuff[0], len-2, cp->crcmode);
|
||||
if (calculated_crc == extracted_crc) {
|
||||
cp->crcfinecnt++;
|
||||
//AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC ok"));
|
||||
if (len > mp->sbsiz) {
|
||||
len = mp->sbsiz;
|
||||
}
|
||||
for (uint16_t i=8; i<=cp->teleendpos - 8 - mp->sbsiz; i++) {
|
||||
if (cp->crcbuff[i] == SML_SYNC || ((mp->flag & NO_SYNC_FLG) != 0)) {
|
||||
if (i+len > cp->teleendpos) len--;
|
||||
memcpy(mp->sbuff, &cp->crcbuff[i],len);
|
||||
SML_Decode(meters);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cp->crcfailcnt++;
|
||||
// CRC is invalid, log an error
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC error: len: %d file-crc: %04x calc-crc: %04x failcnt: %d okcnt: %d mode: %d state: %d"), cp->teleendpos, extracted_crc, calculated_crc, cp->crcfailcnt, cp->crcfinecnt, cp->crcmode, cp->crcdetectstate);
|
||||
//Hexdump(&cp->crcbuff[0], cp->crcbuff_pos);
|
||||
}
|
||||
//auto-detect crc-mode from fine/fail-cnt if autodetect is running
|
||||
if (cp->crcdetectstate>0){ //state=0 autodetect running
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SML: CRC autodetection in progress. state: %d. probing mode: %d failcnt: %d okcnt: %d"), cp->crcdetectstate, cp->crcmode, cp->crcfailcnt, cp->crcfinecnt );
|
||||
//check how far we have come an decide how to go on
|
||||
if (cp->crcfailcnt>3) { //seems bad choice
|
||||
if (cp->crcdetectstate>25) {
|
||||
AddLog(LOG_LEVEL_INFO, "SML: CRC autodetection failed, you can turn of CRC checks of via removing '1,soC=<bufsz>,<mode>' from your meter definition.");
|
||||
} else {
|
||||
cp->crcdetectstate++;
|
||||
}
|
||||
cp->crcmode++;
|
||||
if(cp->crcmode>11) cp->crcmode=0; //mode 0-11 supported (6-11 are 1-5 with reversed byte order)
|
||||
//reset counters and start over
|
||||
cp->crcfailcnt=0;
|
||||
cp->crcfinecnt=0;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC mode auto-changed to: %d"), cp->crcmode);
|
||||
}
|
||||
if (cp->crcfinecnt>3) {
|
||||
//fine, stop detecting now
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SML: CRC autodetection ok after probe #%d selected mode: %d"), cp->crcdetectstate, cp->crcmode);
|
||||
cp->crcdetectstate=0;
|
||||
}
|
||||
}
|
||||
cp->teleendpos=-1;
|
||||
cp->telestartpos=-1;
|
||||
cp->crcbuff_pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SML_DECRYPT
|
||||
if (mp->use_crypt) {
|
||||
if (mp->hp) {
|
||||
@ -1433,7 +1592,7 @@ void sml_shift_in(uint32_t meters, uint32_t shard) {
|
||||
if (timediff > mp->tout_ms) {
|
||||
mp->hp->len = 0;
|
||||
mp->spos = 0;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SML: sync"));
|
||||
AddLog(LOG_LEVEL_DEBUG, "SML: sync");
|
||||
}
|
||||
mp->lastms = millis();
|
||||
uint16_t len;
|
||||
@ -2916,7 +3075,18 @@ struct METER_DESC *mp = &meter_desc[mnum];
|
||||
mp->crypflags = strtol(cp, &cp, 10);
|
||||
break;
|
||||
#endif // USE_SML_DECRYPT
|
||||
case '6':
|
||||
#ifdef USE_SML_CRC
|
||||
case 'C': //1,=soC,<bufsize>,<crcmode> example: 1,=soC,1024,0 (mode=x25,1=ccitt,15=autodetect)
|
||||
cp += 2;
|
||||
mp->so_sml_crc = strtol(cp, &cp, 10)&0x0fff;
|
||||
if (*cp == ',') {
|
||||
cp++;
|
||||
mp->so_sml_crc |= strtol(cp, &cp, 10)<<12;
|
||||
}
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC specialoptions (=soC) so_sml_crc='%x'"),mp->so_sml_crc);
|
||||
break;
|
||||
#endif // USE_SML_CRC
|
||||
case '6':
|
||||
cp += 2;
|
||||
mp->tout_ms = strtol(cp, &cp, 10);
|
||||
break;
|
||||
@ -3008,6 +3178,17 @@ void reset_sml_vars(uint16_t maxmeters) {
|
||||
mp->so_obis1 = 0;
|
||||
mp->so_obis2 = 0;
|
||||
#endif
|
||||
#ifdef USE_SML_CRC
|
||||
AddLog(LOG_LEVEL_INFO, "SML: CRC reset");
|
||||
struct SML_CRC_DATA* cp = mp->sml_crc_data;
|
||||
if (cp && (mp->so_sml_crc & 0x0fff)) {
|
||||
AddLog(LOG_LEVEL_INFO, "SML: CRC free buffer");
|
||||
free(mp->sml_crc_data->crcbuff);
|
||||
free(mp->sml_crc_data);
|
||||
mp->sml_crc_data=0;
|
||||
}
|
||||
mp->so_sml_crc=0;
|
||||
#endif // USE_SML_CRC
|
||||
mp->so_flags.data = 0;
|
||||
// addresses a bug in meter DWS74
|
||||
#ifdef DWS74_BUG
|
||||
@ -3056,6 +3237,9 @@ void reset_sml_vars(uint16_t maxmeters) {
|
||||
memset(mp->auth, 0, SML_CRYPT_SIZE);
|
||||
#endif
|
||||
#endif // USE_SML_DECRYPT
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -3369,7 +3553,39 @@ dddef_exit:
|
||||
// 1,=h—————————————
|
||||
if (!strncmp_P(lp1 + 1, PSTR(",=h"), 3) || !strncmp_P(lp1 + 1, PSTR(",=so"), 4)) {
|
||||
if (!strncmp_P(lp1 + 1, PSTR(",=so"), 4)) {
|
||||
SpecOptions(lp1 + 5, mnum - 1);
|
||||
SpecOptions(lp1 + 5, mnum - 1);
|
||||
|
||||
#ifdef USE_SML_CRC
|
||||
if (mmp->so_sml_crc & 0x0fff) {
|
||||
AddLog(LOG_LEVEL_INFO, "SML: CRC active -> init");
|
||||
if (mmp->sml_crc_data) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC config change - reinit. Buffersize: %d mode: %d"), mmp->so_sml_crc & 0x0fff, (mmp->so_sml_crc & 0xf000)>>12);
|
||||
free(mmp->sml_crc_data->crcbuff);
|
||||
free(mmp->sml_crc_data);
|
||||
}
|
||||
struct SML_CRC_DATA* cp = (struct SML_CRC_DATA*)calloc(sizeof(struct SML_CRC_DATA), 1);
|
||||
cp->telestartpos=-1;
|
||||
cp->teleendpos=-1;
|
||||
memory += sizeof(struct SML_CRC_DATA);
|
||||
cp->crcbuff = (uint8_t*)calloc(mmp->so_sml_crc & 0x0fff, 1);
|
||||
memory += (mmp->so_sml_crc & 0x0fff);
|
||||
cp->crcmode=(mmp->so_sml_crc & 0xf000)>>12;
|
||||
if (cp->crcmode == 15) {
|
||||
//start autodetection probe mode 0 first
|
||||
cp->crcmode=0;
|
||||
cp->crcdetectstate=1;
|
||||
AddLog(LOG_LEVEL_INFO, "SML: CRC mode autodetect");
|
||||
} else {
|
||||
//keep mode as given, turn off autodetect
|
||||
if (cp->crcmode > 11) cp->crcmode=0;
|
||||
cp->crcdetectstate=0;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: CRC mode %d"),cp->crcmode);
|
||||
}
|
||||
mmp->sml_crc_data=cp;
|
||||
}
|
||||
#endif // USE_SML_CRC
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
sml_globs.maxvars++;
|
||||
@ -3399,7 +3615,7 @@ next_line:
|
||||
*tp = 0;
|
||||
sml_globs.meter_p = sml_globs.script_meter;
|
||||
|
||||
// set serial buffers
|
||||
// set serial and crc buffers
|
||||
for (uint32_t meters = 0; meters < sml_globs.meters_used; meters++ ) {
|
||||
struct METER_DESC *mp = &meter_desc[meters];
|
||||
if (mp->sbsiz) {
|
||||
@ -3407,7 +3623,6 @@ next_line:
|
||||
memory += mp->sbsiz;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize hardware
|
||||
typedef void (*function)();
|
||||
uint8_t cindex = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user