/**************************************************************************** * F i l e D a t a * $Id: CRC.h,v 1.5 2009-06-12 18:39:15 pam-rm2 Exp $ * $Revision: 1.5 $ * $Date: 2009-06-12 18:39:15 $ * $RCSfile: CRC.h,v $ * **************************************************************************** * S W D e v e l o p m e n t E n v i r o n m e n t * * $Author: pam-rm2 $ * : *****************************************************************************/ #ifndef CRC_H #define CRC_H #define BYTE unsigned char #define UINT32 unsigned int #define UINT16 unsigned short #include /** Example of CAST macro at work. public domain demo by Bob Stout. * * Example of CAST macro at work * * union { * char ch[4]; * int i[2]; * } my_union; * * long longvar; * * longvar = (long)my_union; Illegal cast * longvar = CAST(long, my_union); Legal cast * */ #define CM_CAST(new_type,old_object) (*((new_type *)&(old_object))) #define CM_HI_UINT16(x) ( (BYTE)( ((x) & 0xff00)>>8 ) ) #define CM_LO_UINT16(x) ( (BYTE)( ((x) & 0x00ff) ) ) #define CM_HI_UINT32(x) ( (UINT16)( ((x) & 0xffff0000)>>16 ) ) #define CM_LO_UINT32(x) ( (UINT16)( ((x) & 0x0000ffff) ) ) #define CM_HIHI_UINT32(x) ( (BYTE)( ((x) & 0xff000000)>>24 ) ) #define CM_LOHI_UINT32(x) ( (BYTE)( ((x) & 0x00ff0000)>>16 ) ) #define CM_HILO_UINT32(x) ( (BYTE)( ((x) & 0x0000ff00)>> 8 ) ) #define CM_LOLO_UINT32(x) ( (BYTE)( ((x) & 0x000000ff) ) ) /** Macro READ_NEXT_BITS_UINT(wordlen,p,offset,n,res) this mascro scans bits for a 'wordlen'-bit long word. 'wordlen' can be 8,16,32... It reads the next 'n' bits starting after the 'offset'-th bit of the 'wordlen'-bit word pointed by p. store the result in 'res', and increment properly both 'offset' and 'p' such that they can be reused in the text invocation of the macro. \a p unsigned 'wordlen'-bit pointer (ie. wordlen==16, then unsinged short int * in i386 arch) varibale name. it points to the word to scan. it is incremented automatically by the macro. \a offset unsigned 8 bit variable name (unsigned char?). Must be an l-value. it holds the number of bit already read in the most significant part of the current pointer (*p). Should be used always the same variable while a scanning session. This value must be initialized to zero and should be always less then 'wordlen'. \a n the number of bits to read. Can be a r-value. Must be 0 <= n <= 'wordlen'. if n is zero (senseless), both 'p' and 'offset' are unchanged and 0 is returned in 'res'. \a res unsigned 'wordlen'-bit variable name (i.e wordlen==16, then unsigned short int? on i386 arch) in which to store the requested 'n' bits. they are returned in the less significat part of 'res'. If n<'wordlen', then the most significant bits of 'res' are padded to zero. before using he macro the first time you have to: (let's assume 'wordlen' fixed to 16 and an i386 arch.) 1) choose an unsigned short pointer to pass as 'p', and initialize it to the sequence of bits to scan from. 2) choose an unsigned char variable to pass as 'offset' and initialize it to zero (or some other value X<16, if you want to skip the first X bits) 3) choose an unsigned short to return the result. */ #define CM_READ_NEXT_BITS_UINT(wordlen,p,offset,n,res) \ do { \ res = (*p << offset); \ res >>= (wordlen-(n)); \ if(n<=wordlen-offset) { \ offset=(offset+(n))%wordlen; \ if(offset==0) \ p++; \ }else{ \ p++; \ res |= *p>>(wordlen*2-offset-(n)); \ offset+=(n)-wordlen; \ } \ }while(0) /* Wrapper to 8,16,32,64 bit link wrapper to READ_NEXT_BITS_UINT : */ #define CM_READ_NEXT_BITS_UINT8(p,offset,n,res) CM_READ_NEXT_BITS_UINT(8 ,p,offset,n,res) #define CM_READ_NEXT_BITS_UINT16(p,offset,n,res) CM_READ_NEXT_BITS_UINT(16,p,offset,n,res) #define CM_READ_NEXT_BITS_UINT32(p,offset,n,res) CM_READ_NEXT_BITS_UINT(32,p,offset,n,res) #define CM_READ_NEXT_BITS_UINT64(p,offset,n,res) CM_READ_NEXT_BITS_UINT(64,p,offset,n,res) #define CM_GET_BIT(exp,n) (((exp) >> ((n)-1)) & 0x1) /* Thees macros write a 16 or 32 bits in BigEndian fascion in a (unsigned char*) avoiding the addressing alignement problem and also increment ptr - ptr must be a (unsigned char*) pointer (l-value) - byte must be a (unsigned char) (r-value) - word must be a (unsigned short int) (r-value) - dword must be a (unsigned int) (r-value) */ #define CM_WRITE_BE_UINT8(ptr,byte) do { *ptr = (unsigned char)(byte); ptr++;} while(0) #define CM_WRITE_BE_UINT16(ptr,word) do { \ CM_WRITE_BE_UINT8(ptr,((word)>>8)); \ CM_WRITE_BE_UINT8(ptr,(word)); \ } while(0) #define CM_WRITE_BE_UINT32(ptr,dword) do { \ CM_WRITE_BE_UINT8(ptr,(dword)>>24); \ CM_WRITE_BE_UINT8(ptr,(dword)>>16); \ CM_WRITE_BE_UINT8(ptr,(dword)>>8); \ CM_WRITE_BE_UINT8(ptr,(dword)); \ } while(0) /* Thees macros read a 16 or 32 bits in BigEndian fascion from a (unsigned char*) avoiding the addressing alignement problem and also increment ptr - ptr must be a (unsigned char*) pointer (l-value) - byte and temp must be a (unsigned char) (l-value) - word must be a (unsigned short int) (l-value) - dword must be a (unsigned int) (l-value) */ #define CM_READ_BE_UINT8(ptr,byte) do { byte = *(ptr); (ptr)++; } while(0) #define CM_READ_BE_UINT16(ptr,word,temp) do { \ CM_READ_BE_UINT8(ptr,temp); \ word = ((unsigned short int)temp) << 8; \ CM_READ_BE_UINT8(ptr,temp); \ word |= temp; \ } while(0) #define CM_READ_BE_UINT32(ptr,word,temp) do { \ CM_READ_BE_UINT8(ptr,temp); \ word = ((unsigned int)temp) << 24; \ CM_READ_BE_UINT8(ptr,temp); \ word |= ((unsigned int)temp) << 16; \ CM_READ_BE_UINT8(ptr,temp); \ word |= ((unsigned int)temp) << 8; \ CM_READ_BE_UINT8(ptr,temp); \ word |= ((unsigned int)temp); \ } while(0) /** Univeral BIT converter to 2 registers set with different resolution. Used in Microsecond to register converte for data time out and event time out and other same-style register. \a v is the value in some unit \a unit_h is the resolution of the MSD-part. must be in same unit of v. \a no_bit_h is the number of bits of the MSD-part. \a unit_l is the resolution of the LSD-part. must be in same unit of v. \a no_bit_l is the number of bits of the LSD-part. \example (case of ETO) Suppose to have 2 8-bit registers ETO1 (8 bit,LSB) and ETO2 (8 bit,HSB): ETO2 have a resoluion of 65 microsec; ETOHSB have a resolution of 16 millisec; This will format a value of 1 millisecond (unit is in microsecond) the usage is: CM_TIME2REG(1000,16*1000,8,65,8) */ //#define CM_TIME2REG(v,unit_h,no_bit_h,unit_l,no_bit_l) ((((v)/(unit_h))<<(no_bit_l) ) | ((((v)%(unit_h))/(unit_l)) & ~((0xffffffff)<<((no_bit_l)+(no_bit_h))))) //#define CM_INT_UNUSED 0 /** Compute a 8 bit CRC based on a \a data, whith a \a old pre-computed crc. */ /** old ---> the old pre-computed crc */ /** data ---> the data to compute crc for */ BYTE CM_crc8_8(BYTE old, BYTE data); UINT32 CM_Compute_CRC8_8(UINT32 oldcrc ,BYTE *buffer ,UINT32 length ); UINT16 CM_CRC16(BYTE* adrs, UINT16 Crc); UINT16 CM_Compute_CRC16(UINT16 oldcrc,BYTE *buffer,UINT32 length); BYTE* charToUnsignedChar(char buffer[], UINT32 length); #endif /* CRC_H */