| | #include <stdint.h>
template<typename BitsType>
BitsType makeMask( )
{
return ~(BitsType)0;
}
template<typename BitsType>
inline
BitsType makeMostSignificantBit( )
{
const BitsType mask = makeMask<BitsType>();
return mask - (mask>>1); //MSBit;
}
uint8_t revertBits( uint8_t u )
{
// 0x00 (0000) -> 0x00 (0000)
// 0x01 (0001) -> 0x08 (1000)
// 0x02 (0010) -> 0x04 (0100)
// 0x03 (0011) -> 0x0C (1100)
// 0x04 (0100) -> 0x02 (0010)
// 0x05 (0101) -> 0x0A (1010)
// 0x06 (0110) -> 0x06 (0110)
// 0x07 (0111) -> 0x0E (1110)
// 0x08 (1000) -> 0x01 (0001)
// 0x09 (1001) -> 0x09 (1001)
// 0x0A (1010) -> 0x05 (0101)
// 0x0B (1011) -> 0x0D (1101)
// 0x0C (1100) -> 0x03 (0011)
// 0x0D (1101) -> 0x0B (1011)
// 0x0E (1110) -> 0x07 (0111)
// 0x0F (1111) -> 0x0F (1111)
static uint8_t revertTable[16] = { 0x00, 0x08, 0x04, 0x0C
, 0x02, 0x0A, 0x06, 0x0E
, 0x01, 0x09, 0x05, 0x0D
, 0x03, 0x0B, 0x07, 0x0F
};
return revertTable[ (u&0xF0)>>4 ]
| (revertTable[ (u&0x0F) ] << 4)
;
}
uint16_t revertBits( uint16_t u )
{
return (uint16_t)revertBits( (uint8_t)(u>>8 ) )
| ((uint16_t)revertBits( (uint8_t)(u&0xFF) )<<8)
;
}
uint32_t revertBits( uint32_t u )
{
return (uint32_t)revertBits( (uint16_t)(u>>16 ) )
| ((uint32_t)revertBits( (uint16_t)(u&0xFFFF) )<<16)
;
}
template<typename BitsType>
BitsType revertBits( BitsType bits, bool revert )
{
return revert ? revertBits(bits) : bits;
}
// https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials
// 1 [0 0 0 1 |0 0 0 0 |0 0 1 0 |0 0 0 1] Normal
// [1 0 0 0 |0 1 0 0 |0 0 0 0 |1 0 0 0] 1 Reverse
// 1 [0 0 0 0 |1 0 0 0 |0 0 0 1 |0 0 0 1] Reciprocal
//
// Reciprocal - подразымевающаяся в N+1 разряде единица всасывается сдвигом право,
// затем это число реверсируется
template<typename BitsType>
BitsType reciprocalBits( BitsType bits, bool revert )
{
//if (!reciprocal) return bits;
//BitsType mask = ~(CrcType)0;
BitsType msb = makeMostSignificantBit<BitsType>();
BitsType res = (bits>>1)|msb;
return revert ? res : revertBits<BitsType>( res, true);
}
enum class CrcTransformType
{
normal,
reversed,
reciprocal,
reversed_reciprocal
};
template<typename BitsType>
BitsType crcPrepareValue( BitsType bits, CrcTransformType trt )
{
switch(trt)
{
case CrcTransformType::reversed:
return revertBits(bits);
case CrcTransformType::reciprocal:
return reciprocalBits(bits, false);
case CrcTransformType::reversed_reciprocal:
return reciprocalBits(bits, false);
default:
return bits;
}
}
template<typename UintType>
UintType uintUnaryMinus( UintType u )
{
return -u;
}
template<>
inline
uint8_t uintUnaryMinus<uint8_t>(uint8_t u)
{
return (uint8_t)(-((int8_t)u));
}
template<>
inline
uint16_t uintUnaryMinus<uint16_t>(uint16_t u)
{
return (uint16_t)(-((int16_t)u));
}
template<>
inline
uint32_t uintUnaryMinus<uint32_t>(uint32_t u)
{
return (uint32_t)(-((int32_t)u));
}
// Check : 0xF7 ("123456789")
// Check : 0x29B1 ("123456789")
// Check : 0xCBF43926 ("123456789")
template< typename CrcType, CrcType NBits, CrcType Poly, bool revert >
CrcType crcStepImpl( CrcType crc, uint8_t byte )
{
#if 1
const CrcType nshift = NBits - 8; //NBits>16 ? 16 : NBits - 8; //NBits - 8; //NShift;
const CrcType mask = makeMask<CrcType>();
const CrcType msbit = makeMostSignificantBit<CrcType>();
const CrcType poly = Poly;
if (nshift)
crc ^= ((CrcType)byte);// << nshift;
else
crc ^= ((CrcType)byte); // << NShift;
for ( auto i = 0u; i != 8u; ++i)
{
//crc = crc & 1 ? (crc >> 1) ^ poly : crc >> 1;
crc = crc & msbit ? (crc << 1) ^ poly : crc << 1;
crc &= mask;
//crc = (crc >> 1) ^ (- (CrcType)(crc & 1) & poly);
//crc = (crc >> 1) ^ (uintUnaryMinus<CrcType>(crc & 1) & poly);
//crc = (crc << 1) ^ (uintUnaryMinus<CrcType>(crc & msbit) & poly);
}
#else
if (NShift)
crc ^= ((CrcType)byte) << NShift;
else
crc ^= ((CrcType)byte); // << NShift;
for ( auto i = 0u; i != 8u; ++i)
{
crc = crc & MSBit ? (crc << 1) ^ Poly : crc << 1;
}
#endif
return crc;
}
//template< typename CrcType, CrcType MSBit, CrcType NShift, CrcType Poly, CrcType Init >
template< typename CrcType, CrcType NBits, CrcType Poly, bool revert, CrcType XorOut, CrcType Init >
CrcType crcImpl( const uint8_t *pBuf, size_t len )
{
CrcType crc = Init;
while(len--)
{
crc = crcStepImpl< CrcType, NBits, Poly, revert >( crc, *pBuf++ );
}
return crc ^ XorOut;
//return revertBits(crc, revert) ^ XorOut;
//return revertBits( (CrcType)(crc ^ XorOut), revert) ;
}
template< uint8_t Poly = 0x31u
, bool revert = false
, uint8_t XorOut = 0x00u
, uint8_t Init = 0xFFu
>
uint8_t crc8( const uint8_t *pBuf, size_t len )
{
return crcImpl< uint8_t, 8u, Poly, revert, XorOut, Init >( pBuf, len );
}
template< uint16_t Poly = 0x1021u
, bool revert = false
, uint16_t XorOut = 0x0000u
, uint16_t Init = 0xFFFFu
>
uint16_t crc16( const uint8_t *pBuf, size_t len )
{
return crcImpl< uint16_t, 16u, Poly, revert, XorOut, Init >( pBuf, len );
}
template< uint32_t Poly = 0x04C11DB7u
, bool revert = true
, uint32_t XorOut = 0xFFFFFFFFu
, uint32_t Init = 0xFFFFFFFFu
>
uint32_t crc32( const uint8_t *pBuf, size_t len )
{
return crcImpl< uint32_t, 32u, Poly, revert, XorOut, Init >( pBuf, len );
}
|