/[avr-libc]/avr-libc/include/avr/crc16.h
ViewVC logotype

Diff of /avr-libc/include/avr/crc16.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.9 by joerg_wunsch, Sun Aug 14 21:44:54 2005 UTC revision 1.10 by joerg_wunsch, Sat Nov 5 22:23:15 2005 UTC
# Line 1  Line 1 
1  /* Copyright (c) 2002, 2003, 2004  Marek Michalkiewicz  /* Copyright (c) 2005 Joerg Wunsch
2     All rights reserved.     All rights reserved.
3    
4     Redistribution and use in source and binary forms, with or without     Redistribution and use in source and binary forms, with or without
# Line 33  Line 33 
33  #ifndef _AVR_CRC16_H_  #ifndef _AVR_CRC16_H_
34  #define _AVR_CRC16_H_  #define _AVR_CRC16_H_
35    
36  #include <inttypes.h>  #warning "This file has been moved to <util/crc16.h>."
37    #include <util/crc16.h>
 /** \defgroup avr_crc <avr/crc16.h>: CRC Computations  
     \code#include <avr/crc16.h>\endcode  
   
     This header file provides a optimized inline functions for calculating 16  
     bit cyclic redundancy checks (CRC) using common polynomials.  
   
     \par References:  
   
     \par  
   
     See the Dallas Semiconductor app note 27 for 8051 assembler example and  
     general CRC optimization suggestions. The table on the last page of the  
     app note is the key to understanding these implementations.  
   
     \par  
   
     Jack Crenshaw's "Impementing CRCs" article in the January 1992 isue of \e  
     Embedded \e Systems \e Programming. This may be difficult to find, but it  
     explains CRC's in very clear and concise terms. Well worth the effort to  
     obtain a copy. */  
   
 /** \ingroup avr_crc  
     Optimized CRC-16 calcutation.  
   
     Polynomial: x^16 + x^15 + x^2 + 1 (0xa001)<br>  
     Initial value: 0xffff  
   
     This CRC is normally used in disk-drive controllers. */  
   
 static __inline__ uint16_t  
 _crc16_update(uint16_t __crc, uint8_t __data)  
 {  
         uint8_t __tmp;  
         uint16_t __ret;  
   
         __asm__ __volatile__ (  
                 "eor %A0,%2" "\n\t"  
                 "mov %1,%A0" "\n\t"  
                 "swap %1" "\n\t"  
                 "eor %1,%A0" "\n\t"  
                 "mov __tmp_reg__,%1" "\n\t"  
                 "lsr %1" "\n\t"  
                 "lsr %1" "\n\t"  
                 "eor %1,__tmp_reg__" "\n\t"  
                 "mov __tmp_reg__,%1" "\n\t"  
                 "lsr %1" "\n\t"  
                 "eor %1,__tmp_reg__" "\n\t"  
                 "andi %1,0x07" "\n\t"  
                 "mov __tmp_reg__,%A0" "\n\t"  
                 "mov %A0,%B0" "\n\t"  
                 "lsr %1" "\n\t"  
                 "ror __tmp_reg__" "\n\t"  
                 "ror %1" "\n\t"  
                 "mov %B0,__tmp_reg__" "\n\t"  
                 "eor %A0,%1" "\n\t"  
                 "lsr __tmp_reg__" "\n\t"  
                 "ror %1" "\n\t"  
                 "eor %B0,__tmp_reg__" "\n\t"  
                 "eor %A0,%1"  
                 : "=r" (__ret), "=d" (__tmp)  
                 : "r" (__data), "0" (__crc)  
                 : "r0"  
         );  
         return __ret;  
 }  
   
 /** \ingroup avr_crc  
     Optimized CRC-XMODEM calculation.  
   
     Polynomial: x^16 + x^12 + x^5 + 1 (0x1021)<br>  
     Initial value: 0x0  
   
     This is the CRC used by the Xmodem-CRC protocol.  
   
     The following is the equivalent functionality written in C.  
   
     \code  
     uint16_t  
     crc_xmodem_update (uint16_t crc, uint8_t data)  
     {  
         int i;  
   
         crc = crc ^ ((uint16_t)data << 8);  
         for (i=0; i<8; i++)  
         {  
             if (crc & 0x8000)  
                 crc = (crc << 1) ^ 0x1021;  
             else  
                 crc <<= 1;  
         }  
   
         return crc;  
     }  
     \endcode */  
   
 static __inline__ uint16_t  
 _crc_xmodem_update(uint16_t __crc, uint8_t __data)  
 {  
     uint16_t __ret;             /* %B0:%A0 (alias for __crc) */  
     uint8_t __tmp1;             /* %1 */  
     uint8_t __tmp2;             /* %2 */  
                                 /* %3  __data */  
   
     __asm__ __volatile__ (  
         "eor    %B0,%3"          "\n\t" /* crc.hi ^ data */  
         "mov    __tmp_reg__,%B0" "\n\t"  
         "swap   __tmp_reg__"     "\n\t" /* swap(crc.hi ^ data) */  
   
         /* Calculate the ret.lo of the CRC. */  
         "mov    %1,__tmp_reg__"  "\n\t"  
         "andi   %1,0x0f"         "\n\t"  
         "eor    %1,%B0"          "\n\t"  
         "mov    %2,%B0"          "\n\t"  
         "eor    %2,__tmp_reg__"  "\n\t"  
         "lsl    %2"              "\n\t"  
         "andi   %2,0xe0"         "\n\t"  
         "eor    %1,%2"           "\n\t" /* __tmp1 is now ret.lo. */  
           
         /* Calculate the ret.hi of the CRC. */  
         "mov    %2,__tmp_reg__"  "\n\t"  
         "eor    %2,%B0"          "\n\t"  
         "andi   %2,0xf0"         "\n\t"  
         "lsr    %2"              "\n\t"  
         "mov    __tmp_reg__,%B0" "\n\t"  
         "lsl    __tmp_reg__"     "\n\t"  
         "rol    %2"              "\n\t"  
         "lsr    %B0"             "\n\t"  
         "lsr    %B0"             "\n\t"  
         "lsr    %B0"             "\n\t"  
         "andi   %B0,0x1f"        "\n\t"  
         "eor    %B0,%2"          "\n\t"  
         "eor    %B0,%A0"         "\n\t" /* ret.hi is now ready. */  
         "mov    %A0,%1"          "\n\t" /* ret.lo is now ready. */  
         : "=d" (__ret), "=d" (__tmp1), "=d" (__tmp2)  
         : "r" (__data), "0" (__crc)  
         : "r0"  
     );  
     return __ret;  
 }  
   
 /** \ingroup avr_crc  
     Optimized CRC-CCITT calculation.  
   
     Polynomial: x^16 + x^12 + x^5 + 1 (0x8408)<br>  
     Initial value: 0xffff  
   
     This is the CRC used by PPP and IrDA.  
   
     See RFC1171 (PPP protocol) and IrDA IrLAP 1.1  
   
     \note Although the CCITT polynomial is the same as that used by the Xmodem  
     protocol, they are quite different. The difference is in how the bits are  
     shifted through the alorgithm. Xmodem shifts the MSB of the CRC and the  
     input first, while CCITT shifts the LSB of the CRC and the input first.  
   
     The following is the equivalent functionality written in C.  
   
     \code  
     uint16_t  
     crc_ccitt_update (uint16_t crc, uint8_t data)  
     {  
         data ^= lo8 (crc);  
         data ^= data << 4;  
   
         return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4)  
                 ^ ((uint16_t)data << 3));  
     }  
     \endcode */  
   
 static __inline__ uint16_t  
 _crc_ccitt_update (uint16_t __crc, uint8_t __data)  
 {  
     uint16_t __ret;  
   
     __asm__ __volatile__ (  
         "eor    %A0,%1"          "\n\t"  
   
         "mov    __tmp_reg__,%A0" "\n\t"  
         "swap   %A0"             "\n\t"  
         "andi   %A0,0xf0"        "\n\t"  
         "eor    %A0,__tmp_reg__" "\n\t"  
   
         "mov    __tmp_reg__,%B0" "\n\t"  
   
         "mov    %B0,%A0"         "\n\t"  
   
         "swap   %A0"             "\n\t"  
         "andi   %A0,0x0f"        "\n\t"  
         "eor    __tmp_reg__,%A0" "\n\t"  
   
         "lsr    %A0"             "\n\t"  
         "eor    %B0,%A0"         "\n\t"  
   
         "eor    %A0,%B0"         "\n\t"  
         "lsl    %A0"             "\n\t"  
         "lsl    %A0"             "\n\t"  
         "lsl    %A0"             "\n\t"  
         "eor    %A0,__tmp_reg__"  
   
         : "=d" (__ret)  
         : "r" (__data), "0" (__crc)  
         : "r0"  
     );  
     return __ret;  
 }  
38    
39  #endif /* _AVR_CRC16_H_ */  #endif /* _AVR_CRC16_H_ */

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26