CRC8 Code

From efiHacks Wiki
Jump to: navigation, search

Contents

8 Bit CRC, Cyclic Redundancy Check

This is the CRC-8 code we use in all of our products. We provide Applications for all of our products for most operating systems. Anything going beyond the scope of these Applications will need this CRC-8 Class or a similar CRC-8 algorithm producing the same results to interface to our products on the host computer side.

The code is table driven by two short CRC-8 encoding arrays and is about as small and fast as it comes with emphasis on small.

CRC-8 C++ Class Code

We like to use C++ and the old x86 windows convention for our integral type names, even the Arm convention refers to a word as a 32 bit quantity.

  • bool to express true / false or 1 / 0
  • char 8-bit signed
  • BYTE 8-bit unsigned
  • short 16-bit signed
  • WORD 16-bit signed
  • int 32-bit signed, Arm assumed
  • UINT 32-bit unsigned, Arm assumed
  • long 32-bit signed
  • DWORD 32-bit unsigned

We use typically 16-bit types in structs and arrays to save memory space, or to indicate that the parameter or return type relates to the type of a struct or array member.

The types long and DWORD are used to express explicitly the need for 32 bits.

Generically we use the types int and UINT for uniformity and since compilers produce the best code (size and speed) for their native implementation types.

CRC-8 C++ Class Header File

//---------------------------------------------------------------------------

class  TCrc8s ;
extern TCrc8s Crc8s ;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

class TCrc8s
{
public :

  enum { eRevCrc8s = 0x13030900 } ;

  static const DWORD cRevNum ;

private :

  enum { eACC  = 0x0000 } ;

  static const BYTE cTblLo[0x10],
  		    cTblHi[0x10] ;

  BYTE	Acc ;

public :

  UINT	Crc(void) const { return Acc ; }
  void	Ini(UINT crc = 0) ;

  UINT	Add(BYTE  x) ;
  UINT	Add(short x) { Add((BYTE)x) ; return Add((BYTE)(x >>  8)) ; }
  UINT	Add(WORD  x) { Add((BYTE)x) ; return Add((BYTE)(x >>  8)) ; }
  UINT	Add(int   x) { Add((WORD)x) ; return Add((WORD)(x >> 16)) ; }
  UINT	Add(UINT  x) { Add((WORD)x) ; return Add((WORD)(x >> 16)) ; }
  UINT	Add(long  x) { Add((WORD)x) ; return Add((WORD)(x >> 16)) ; }
  UINT	Add(DWORD x) { Add((WORD)x) ; return Add((WORD)(x >> 16)) ; }

  UINT	Add(const BYTE *p, UINT cnt) ;
  UINT	Add(const BYTE *p, UINT cnt, UINT ini) ;

} ;
//---------------------------------------------------------------------------
 

CRC-8 C++ Class Code File

This particular CRC-8 implementation uses two short CRC-8 encoding arrays, compared to others using a single 256 byte CRC-8 encoding array. The dual short array method takes a slightly longer computation as the single 256 byte array method ... but execution speed is for sure not the issue in our case.

UINT TCrc8s::Add(BYTE x)
{
  UINT i = Acc ^ x ;
  return   Acc = cTblLo[i & 0x0f] ^ cTblHi[i >> 4 & 0x00ff] ;
} 

And now the whole class code.

//---------------------------------------------------------------------------

TCrc8s Crc8s ;

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

const DWORD TCrc8s::cRevNum = { eRevCrc8s } ;

//---------------------------------------------------------------------------
/* Table for CRC-8 polynomial 0x31,	x^8 + x^5 + x^4 + 1	*/

const BYTE TCrc8s::cTblLo[0x10] = {
  0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
  0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
} ;

const BYTE TCrc8s::cTblHi[0x10] = {
  0x00, 0x9d, 0x23, 0xbe, 0x46, 0xdb, 0x65, 0xf8,
  0x8c, 0x11, 0xaf, 0x32, 0xca, 0x57, 0xe9, 0x74
} ;
//---------------------------------------------------------------------------

void TCrc8s::Ini(UINT crc)
{
  Acc  = crc ;
}
//---------------------------------------------------------------------------

UINT TCrc8s::Add(BYTE x)
{
  UINT i = Acc ^ x ;
  return   Acc = cTblLo[i & 0x0f] ^ cTblHi[i >> 4 & 0x00ff] ;
}
//---------------------------------------------------------------------------

UINT TCrc8s::Add(const BYTE *p, UINT cnt)
{
  while (cnt--) Add(*p++) ;
  return Crc() ;
}
//---------------------------------------------------------------------------

UINT TCrc8s::Add(const BYTE *p, UINT cnt, UINT ini)
{
  Ini(ini) ;
  return Add(p, cnt) ;
}
//---------------------------------------------------------------------------
 

I have to admit that i do NOT have a PhD in CRC theories or similar, so please take the code as working, unless you find something wrong with it, and in this case i would appreciate to know what it might be :)

It has been tested against pre-claimed working code from outside sources.


Note : All published design documentation is Copyright efiLabs.com and its use is without exception FOR NON COMMERCIAL PURPOSE ONLY. For commercial licenses contact efilabs.com ... try us, we're reasonable :)

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox