# -*- coding: utf-8 -*-
# (c) Copyright 2019 Sensirion AG, Switzerland
# from __future__ import absolute_import, division, print_function
[docs]class CrcCalculator(object):
"""
Helper class to calculate arbitrary CRCs. An instance of this class
can be called like a function to calculate the CRC of the passed data.
.. note:: This class is not used within this package, its purpose is to
help users writing drivers for I²C devices which protect the
transferred data with CRCs.
"""
[docs] def __init__(self, width, polynomial, init_value=0, final_xor=0):
"""
Constructs a calculator object with the given CRC parameters.
:param int width:
Number of bits of the CRC (e.g. 8 for CRC-8).
:param int polynomial:
The polynomial of the CRC, without leading '1' (e.g. 0x31 for the
polynomial x^8 + x^5 + x^4 + 1).
:param int init_value:
Initialization value of the CRC. Defaults to 0.
:param int final_xor:
Final XOR value of the CRC. Defaults to 0.
"""
super(CrcCalculator, self).__init__()
self._width = width
self._polynomial = polynomial
self._init_value = init_value
self._final_xor = final_xor
[docs] def __call__(self, data):
"""
Calculate the CRC of the given data.
:param iterable data:
The input data (iterable with values of given bit width, e.g.
list of 8-bit integers).
:return:
The calculated CRC.
:rtype:
int
"""
crc = self._init_value
for value in data:
crc ^= value
for i in range(self._width):
if crc & (1 << (self._width - 1)):
crc = (crc << 1) ^ self._polynomial
else:
crc = crc << 1
crc &= (1 << self._width) - 1
return crc ^ self._final_xor