/****************************************************************************
 *  F i l e   D a t a                                                        
 *  $Id: CRC.h,v 5.1 2006/02/04 12:37:42 kusanagi Exp $
 *  $Revision: 5.1 $ 
 *  $Date: 2006/02/04 12:37:42 $     
 *  $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: kusanagi $                                                                   
 *               :                                                           
 *****************************************************************************/

#ifndef CRC_H
#define CRC_H

#define BYTE       unsigned char 
#define  UINT32 unsigned int 
#define  UINT16 unsigned short 


/**   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 */



