$treeview $search $mathjax $extrastylesheet
avr-libc  2.0.0
$projectbrief
$projectbrief
$searchbox

AVR Libc Home Page

AVRs

AVR Libc Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

crc16.h

Go to the documentation of this file.
00001 /* Copyright (c) 2002, 2003, 2004  Marek Michalkiewicz
00002    Copyright (c) 2005, 2007 Joerg Wunsch
00003    Copyright (c) 2013 Dave Hylands
00004    Copyright (c) 2013 Frederic Nadeau
00005    All rights reserved.
00006 
00007    Redistribution and use in source and binary forms, with or without
00008    modification, are permitted provided that the following conditions are met:
00009 
00010    * Redistributions of source code must retain the above copyright
00011      notice, this list of conditions and the following disclaimer.
00012 
00013    * Redistributions in binary form must reproduce the above copyright
00014      notice, this list of conditions and the following disclaimer in
00015      the documentation and/or other materials provided with the
00016      distribution.
00017 
00018    * Neither the name of the copyright holders nor the names of
00019      contributors may be used to endorse or promote products derived
00020      from this software without specific prior written permission.
00021 
00022   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00023   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00026   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00027   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00028   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00029   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00030   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00031   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032   POSSIBILITY OF SUCH DAMAGE. */
00033 
00034 /* $Id$ */
00035 
00036 #ifndef _UTIL_CRC16_H_
00037 #define _UTIL_CRC16_H_
00038 
00039 #include <stdint.h>
00040 
00041 /** \file */
00042 /** \defgroup util_crc <util/crc16.h>: CRC Computations
00043     \code#include <util/crc16.h>\endcode
00044 
00045     This header file provides a optimized inline functions for calculating
00046     cyclic redundancy checks (CRC) using common polynomials.
00047 
00048     \par References:
00049 
00050     \par
00051 
00052     See the Dallas Semiconductor app note 27 for 8051 assembler example and
00053     general CRC optimization suggestions. The table on the last page of the
00054     app note is the key to understanding these implementations.
00055 
00056     \par
00057 
00058     Jack Crenshaw's "Implementing CRCs" article in the January 1992 isue of \e
00059     Embedded \e Systems \e Programming. This may be difficult to find, but it
00060     explains CRC's in very clear and concise terms. Well worth the effort to
00061     obtain a copy.
00062 
00063     A typical application would look like:
00064 
00065     \code
00066     // Dallas iButton test vector.
00067     uint8_t serno[] = { 0x02, 0x1c, 0xb8, 0x01, 0, 0, 0, 0xa2 };
00068 
00069     int
00070     checkcrc(void)
00071     {
00072     uint8_t crc = 0, i;
00073 
00074     for (i = 0; i < sizeof serno / sizeof serno[0]; i++)
00075         crc = _crc_ibutton_update(crc, serno[i]);
00076 
00077     return crc; // must be 0
00078     }
00079     \endcode
00080 */
00081 
00082 /** \ingroup util_crc
00083     Optimized CRC-16 calculation.
00084 
00085     Polynomial: x^16 + x^15 + x^2 + 1 (0xa001)<br>
00086     Initial value: 0xffff
00087 
00088     This CRC is normally used in disk-drive controllers.
00089 
00090     The following is the equivalent functionality written in C.
00091 
00092     \code
00093     uint16_t
00094     crc16_update(uint16_t crc, uint8_t a)
00095     {
00096     int i;
00097 
00098     crc ^= a;
00099     for (i = 0; i < 8; ++i)
00100     {
00101         if (crc & 1)
00102         crc = (crc >> 1) ^ 0xA001;
00103         else
00104         crc = (crc >> 1);
00105     }
00106 
00107     return crc;
00108     }
00109 
00110     \endcode */
00111 
00112 static __inline__ uint16_t
00113 _crc16_update(uint16_t __crc, uint8_t __data)
00114 {
00115     uint8_t __tmp;
00116     uint16_t __ret;
00117 
00118     __asm__ __volatile__ (
00119         "eor %A0,%2" "\n\t"
00120         "mov %1,%A0" "\n\t"
00121         "swap %1" "\n\t"
00122         "eor %1,%A0" "\n\t"
00123         "mov __tmp_reg__,%1" "\n\t"
00124         "lsr %1" "\n\t"
00125         "lsr %1" "\n\t"
00126         "eor %1,__tmp_reg__" "\n\t"
00127         "mov __tmp_reg__,%1" "\n\t"
00128         "lsr %1" "\n\t"
00129         "eor %1,__tmp_reg__" "\n\t"
00130         "andi %1,0x07" "\n\t"
00131         "mov __tmp_reg__,%A0" "\n\t"
00132         "mov %A0,%B0" "\n\t"
00133         "lsr %1" "\n\t"
00134         "ror __tmp_reg__" "\n\t"
00135         "ror %1" "\n\t"
00136         "mov %B0,__tmp_reg__" "\n\t"
00137         "eor %A0,%1" "\n\t"
00138         "lsr __tmp_reg__" "\n\t"
00139         "ror %1" "\n\t"
00140         "eor %B0,__tmp_reg__" "\n\t"
00141         "eor %A0,%1"
00142         : "=r" (__ret), "=d" (__tmp)
00143         : "r" (__data), "0" (__crc)
00144         : "r0"
00145     );
00146     return __ret;
00147 }
00148 
00149 /** \ingroup util_crc
00150     Optimized CRC-XMODEM calculation.
00151 
00152     Polynomial: x^16 + x^12 + x^5 + 1 (0x1021)<br>
00153     Initial value: 0x0
00154 
00155     This is the CRC used by the Xmodem-CRC protocol.
00156 
00157     The following is the equivalent functionality written in C.
00158 
00159     \code
00160     uint16_t
00161     crc_xmodem_update (uint16_t crc, uint8_t data)
00162     {
00163         int i;
00164 
00165         crc = crc ^ ((uint16_t)data << 8);
00166         for (i=0; i<8; i++)
00167         {
00168             if (crc & 0x8000)
00169                 crc = (crc << 1) ^ 0x1021;
00170             else
00171                 crc <<= 1;
00172         }
00173 
00174         return crc;
00175     }
00176     \endcode */
00177 
00178 static __inline__ uint16_t
00179 _crc_xmodem_update(uint16_t __crc, uint8_t __data)
00180 {
00181     uint16_t __ret;             /* %B0:%A0 (alias for __crc) */
00182     uint8_t __tmp1;             /* %1 */
00183     uint8_t __tmp2;             /* %2 */
00184                                 /* %3  __data */
00185 
00186     __asm__ __volatile__ (
00187         "eor    %B0,%3"          "\n\t" /* crc.hi ^ data */
00188         "mov    __tmp_reg__,%B0" "\n\t"
00189         "swap   __tmp_reg__"     "\n\t" /* swap(crc.hi ^ data) */
00190 
00191         /* Calculate the ret.lo of the CRC. */
00192         "mov    %1,__tmp_reg__"  "\n\t"
00193         "andi   %1,0x0f"         "\n\t"
00194         "eor    %1,%B0"          "\n\t"
00195         "mov    %2,%B0"          "\n\t"
00196         "eor    %2,__tmp_reg__"  "\n\t"
00197         "lsl    %2"              "\n\t"
00198         "andi   %2,0xe0"         "\n\t"
00199         "eor    %1,%2"           "\n\t" /* __tmp1 is now ret.lo. */
00200 
00201         /* Calculate the ret.hi of the CRC. */
00202         "mov    %2,__tmp_reg__"  "\n\t"
00203         "eor    %2,%B0"          "\n\t"
00204         "andi   %2,0xf0"         "\n\t"
00205         "lsr    %2"              "\n\t"
00206         "mov    __tmp_reg__,%B0" "\n\t"
00207         "lsl    __tmp_reg__"     "\n\t"
00208         "rol    %2"              "\n\t"
00209         "lsr    %B0"             "\n\t"
00210         "lsr    %B0"             "\n\t"
00211         "lsr    %B0"             "\n\t"
00212         "andi   %B0,0x1f"        "\n\t"
00213         "eor    %B0,%2"          "\n\t"
00214         "eor    %B0,%A0"         "\n\t" /* ret.hi is now ready. */
00215         "mov    %A0,%1"          "\n\t" /* ret.lo is now ready. */
00216         : "=d" (__ret), "=d" (__tmp1), "=d" (__tmp2)
00217         : "r" (__data), "0" (__crc)
00218         : "r0"
00219     );
00220     return __ret;
00221 }
00222 
00223 /** \ingroup util_crc
00224     Optimized CRC-CCITT calculation.
00225 
00226     Polynomial: x^16 + x^12 + x^5 + 1 (0x8408)<br>
00227     Initial value: 0xffff
00228 
00229     This is the CRC used by PPP and IrDA.
00230 
00231     See RFC1171 (PPP protocol) and IrDA IrLAP 1.1
00232 
00233     \note Although the CCITT polynomial is the same as that used by the Xmodem
00234     protocol, they are quite different. The difference is in how the bits are
00235     shifted through the alorgithm. Xmodem shifts the MSB of the CRC and the
00236     input first, while CCITT shifts the LSB of the CRC and the input first.
00237 
00238     The following is the equivalent functionality written in C.
00239 
00240     \code
00241     uint16_t
00242     crc_ccitt_update (uint16_t crc, uint8_t data)
00243     {
00244         data ^= lo8 (crc);
00245         data ^= data << 4;
00246 
00247         return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) 
00248                 ^ ((uint16_t)data << 3));
00249     }
00250     \endcode */
00251 
00252 static __inline__ uint16_t
00253 _crc_ccitt_update (uint16_t __crc, uint8_t __data)
00254 {
00255     uint16_t __ret;
00256 
00257     __asm__ __volatile__ (
00258         "eor    %A0,%1"          "\n\t"
00259 
00260         "mov    __tmp_reg__,%A0" "\n\t"
00261         "swap   %A0"             "\n\t"
00262         "andi   %A0,0xf0"        "\n\t"
00263         "eor    %A0,__tmp_reg__" "\n\t"
00264 
00265         "mov    __tmp_reg__,%B0" "\n\t"
00266 
00267         "mov    %B0,%A0"         "\n\t"
00268 
00269         "swap   %A0"             "\n\t"
00270         "andi   %A0,0x0f"        "\n\t"
00271         "eor    __tmp_reg__,%A0" "\n\t"
00272 
00273         "lsr    %A0"             "\n\t"
00274         "eor    %B0,%A0"         "\n\t"
00275 
00276         "eor    %A0,%B0"         "\n\t"
00277         "lsl    %A0"             "\n\t"
00278         "lsl    %A0"             "\n\t"
00279         "lsl    %A0"             "\n\t"
00280         "eor    %A0,__tmp_reg__"
00281 
00282         : "=d" (__ret)
00283         : "r" (__data), "0" (__crc)
00284         : "r0"
00285     );
00286     return __ret;
00287 }
00288 
00289 /** \ingroup util_crc
00290     Optimized Dallas (now Maxim) iButton 8-bit CRC calculation.
00291 
00292     Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)<br>
00293     Initial value: 0x0
00294 
00295     See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
00296 
00297     The following is the equivalent functionality written in C.
00298 
00299     \code
00300     uint8_t
00301     _crc_ibutton_update(uint8_t crc, uint8_t data)
00302     {
00303     uint8_t i;
00304 
00305     crc = crc ^ data;
00306     for (i = 0; i < 8; i++)
00307     {
00308         if (crc & 0x01)
00309             crc = (crc >> 1) ^ 0x8C;
00310         else
00311             crc >>= 1;
00312     }
00313 
00314     return crc;
00315     }
00316     \endcode
00317 */
00318 
00319 static __inline__ uint8_t
00320 _crc_ibutton_update(uint8_t __crc, uint8_t __data)
00321 {
00322     uint8_t __i, __pattern;
00323     __asm__ __volatile__ (
00324         "   eor %0, %4" "\n\t"
00325         "   ldi %1, 8" "\n\t"
00326         "   ldi %2, 0x8C" "\n\t"
00327         "1: lsr %0" "\n\t"
00328         "   brcc    2f" "\n\t"
00329         "   eor %0, %2" "\n\t"
00330         "2: dec %1" "\n\t"
00331         "   brne    1b" "\n\t"
00332         : "=r" (__crc), "=d" (__i), "=d" (__pattern)
00333         : "0" (__crc), "r" (__data));
00334     return __crc;
00335 }
00336 
00337 /** \ingroup util_crc
00338     Optimized CRC-8-CCITT calculation.
00339 
00340     Polynomial: x^8 + x^2 + x + 1 (0xE0)<br>
00341     
00342     For use with simple CRC-8<br>
00343     Initial value: 0x0
00344     
00345     For use with CRC-8-ROHC<br>
00346     Initial value: 0xff<br>
00347     Reference: http://tools.ietf.org/html/rfc3095#section-5.9.1
00348     
00349     For use with CRC-8-ATM/ITU<br>
00350     Initial value: 0xff<br>
00351     Final XOR value: 0x55<br>
00352     Reference: http://www.itu.int/rec/T-REC-I.432.1-199902-I/en
00353     
00354     The C equivalent has been originally written by Dave Hylands.
00355     Assembly code is based on _crc_ibutton_update optimization.
00356 
00357     The following is the equivalent functionality written in C.
00358 
00359     \code
00360     uint8_t
00361     _crc8_ccitt_update (uint8_t inCrc, uint8_t inData)
00362     {
00363         uint8_t   i;
00364         uint8_t   data;
00365 
00366         data = inCrc ^ inData;
00367 
00368         for ( i = 0; i < 8; i++ )
00369         {
00370             if (( data & 0x80 ) != 0 )
00371             {
00372                 data <<= 1;
00373                 data ^= 0x07;
00374             }
00375             else
00376             {
00377                 data <<= 1;
00378             }
00379         }
00380         return data;
00381     }
00382     \endcode
00383 */
00384 
00385 static __inline__ uint8_t
00386 _crc8_ccitt_update(uint8_t __crc, uint8_t __data)
00387 {
00388     uint8_t __i, __pattern;
00389     __asm__ __volatile__ (
00390         "    eor    %0, %4" "\n\t"
00391         "    ldi    %1, 8" "\n\t"
00392         "    ldi    %2, 0x07" "\n\t"
00393         "1:  lsl    %0" "\n\t"
00394         "    brcc   2f" "\n\t"
00395         "    eor    %0, %2" "\n\t"
00396         "2:  dec    %1" "\n\t"
00397         "    brne   1b" "\n\t"
00398         : "=r" (__crc), "=d" (__i), "=d" (__pattern)
00399         : "0" (__crc), "r" (__data));
00400     return __crc;
00401 }
00402 
00403 #endif /* _UTIL_CRC16_H_ */
 All Data Structures Files Functions Variables Typedefs Enumerations Defines