| | У>#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 );
У>}
У>
|