defmodule CRC do use Bitwise @moduledoc """ This module is used to calculate CRC (Cyclic Redundancy Check) values for binary data. It uses NIF functions written in C to interate over the given binary calculating the CRC checksum value. """ @compile {:autoload, false} @on_load {:init, 0} @doc """ Initilizes the module by loading NIFs """ def init do path = :filename.join(:code.priv_dir(:crc), 'crc_nif') :ok = :erlang.load_nif(path, 0) end @doc """ Calculates a 8-bit CRC with polynomial x^8+x^6+x^3+x^2+1, 0x14D. Chosen based on Koopman, et al. (0xA6 in his notation = 0x14D >> 1): http://www.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf seed defaults to 0xFF if one is not given """ @spec crc_8(binary, number) :: number def crc_8(<>, seed \\ 0xFF) do _calc_8(data, seed) end @doc """ Calculates a 16-bit ANSI CRC checksum for the provided binary """ @spec crc_16(binary) :: number def crc_16(<>) do _calc_16(data) end @doc """ Calculates a 16-bit CCITT CRC with the given seed, seed defaults to 0xFFFF if one is not given """ @spec ccitt_16(binary, number) :: number def ccitt_16(<>, seed \\ 0xFFFF) do _calc_16_ccitt(data, seed) end @doc """ Calculates a 16-bit CCITT XMODEM CRC """ @spec ccitt_16_xmodem(binary) :: number def ccitt_16_xmodem(<>) do _calc_16_ccitt(data, 0x0000) end @doc """ Calculates a 16-bit CCITT 0x1D0F CRC """ @spec ccitt_16_1D0F(binary) :: number def ccitt_16_1D0F(<>) do _calc_16_ccitt(data, 0x1D0F) end @doc """ Calculates a 16-bit modbus CRC """ @spec crc_16_modbus(binary) :: number def crc_16_modbus(<>) do _calc_16_modbus(data) end # # @spec crc_16_sick(binary) :: number # def crc_16_sick(<>) do # 0x0000 # end # # @spec crc_dnp(binary) :: number # def crc_dnp(<>) do # 0x0000 # end @doc """ Calculates an XOR checksum for the given binary """ @spec checksum_xor(binary) :: number def checksum_xor(<>) do _checksum_xor(data, 0) end defp _calc_8(_, _), do: "CRC NIF not loaded" defp _calc_16(_), do: "CRC NIF not loaded" defp _calc_16_ccitt(_, _), do: "CRC NIF not loaded" defp _calc_16_modbus(_), do: "CRC NIF not loaded" defp _checksum_xor(<<>>, sum), do: sum defp _checksum_xor(<>, sum) do _checksum_xor(rest, Bitwise.bxor(val, sum)) end end