packages feed

crc16-0.1.1: Data/Digest/CRC16.hs

{- | crc16 ccitt

   1) MSB first 1021 x^16 + x^12 + x^5 + 1 

   2) LSB first 8048

-}
module Data.Digest.CRC16 (
     -- * CRC16 method
     crc16Update
    ) where

import Data.Word(Word8,Word16)
import Data.Bits


-- | crc16 calculation
-- This uses the simple method based on /bit shifting/.
-- See the unittests for an example.
--
crc16Update :: Word16      -- ^ polynomial
            -> Bool        -- ^ inverse bits
            -> Word16      -- ^ initial crc
            -> Word8       -- ^ data byte
            -> Word16      -- ^ new crc
crc16Update poly rev crc b =
    foldl (crc16UpdateBit poly) new_crc [1..(bitSize b)]
    where
        new_crc = crc `xor` shiftL (fromIntegral b' :: Word16) 8
        b' = if rev
                then reverseBits b
                else b




crc16UpdateBit :: Word16 -> Word16 -> Int -> Word16
crc16UpdateBit poly crc _ =
    if (crc .&. 0x8000) /= 0x0000
        then shiftL crc 1 `xor` poly
        else shiftL crc 1



-- | Reverse the bits in a byte
--
-- 7..0 becomes 0..7
--
reverseBits :: Word8 -> Word8
reverseBits b =
  shiftL (b .&. 0x01) 7
  .|. shiftL (b .&. 0x02) 5
  .|. shiftL (b .&. 0x04) 3
  .|. shiftL (b .&. 0x08) 1
  .|. shiftR (b .&. 0x10) 1
  .|. shiftR (b .&. 0x20) 3
  .|. shiftR (b .&. 0x40) 5
  .|. shiftR (b .&. 0x80) 7