Skip to content

Commit

Permalink
arbitrary bit-sized input processing working correctly, lookup table …
Browse files Browse the repository at this point in the history
…created for feed_width (ie. byte) instead of width_bits (ie. 9/16/32)
  • Loading branch information
smarek committed Jan 21, 2022
1 parent f96626f commit 840291e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 25 deletions.
51 changes: 34 additions & 17 deletions okdmr/dmrlib/etsi/crc/crc.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ class BitCrcConfiguration:
reverse_input_bytes: bool = False
reverse_output_bytes: bool = False

@property
def feed_width_bits(self) -> int:
if self.width_bits % 8 == 0:
return 8

for candidate in reversed(range(1, 16)):
if self.width_bits % candidate == 0:
return candidate

return 1


class BitCrcRegisterBase(AbstractBitCrcRegister):
"""
Expand Down Expand Up @@ -131,8 +142,10 @@ def update(self, bits: bitarray) -> bitarray:
if self._config.reverse_input_bytes:
bits.bytereverse()

for start_bit in range(0, len(bits), self._config.width_bits):
self._process_bits(bits[start_bit : start_bit + self._config.width_bits])
feed_width = self._config.feed_width_bits

for start_bit in range(0, len(bits), feed_width):
self._process_bits(bits[start_bit : start_bit + feed_width])

return self.register

Expand Down Expand Up @@ -166,7 +179,7 @@ def reverse(self) -> bitarray:
return self.register

def _is_division_possible(self):
return ba2int(self.register & self._topbit) > 0
return self.register >= self._topbit

@property
def register(self) -> bitarray:
Expand All @@ -191,8 +204,9 @@ def _process_bits(self, bits: bitarray):
if len(bits) < 1:
return self.register

self.register = int2ba(
ba2int(bits) ^ ba2int(self.register), length=self._config.width_bits
self.register ^= int2ba(
ba2int(bits) << (self._config.width_bits - self._config.feed_width_bits),
length=self._config.width_bits,
)
polynomial: bitarray = int2ba(
self._config.polynomial, length=self._config.width_bits
Expand All @@ -205,7 +219,7 @@ def _process_bits(self, bits: bitarray):
return self.register


class TableBasedBitCrcRegister(BitCrcRegisterBase):
class TableBasedBitCrcRegister(BitCrcRegister):
"""
Lookup table based crc register.
Expand All @@ -222,7 +236,7 @@ def __init__(self, configuration: Union[BitCrcConfiguration, enum.Enum]):
:param configuration: used for the crc algorithm.
:attention: creating a table based register initially might take some extra time, due to the
fact that some lookup tables need to be calculated/initialized .
fact that lookup table needs to be calculated/initialized .
"""
super().__init__(configuration)
self._lookup_table = bits_create_lookup_table(
Expand All @@ -233,14 +247,16 @@ def _process_bits(self, bits: bitarray):
"""
See BitCrcRegisterBase._process_bits
"""
if len(bits) != len(self.register):
print("correct", bits, ba2int(bits))
bits = int2ba(ba2int(bits), length=len(self.register))
print("correct", bits, ba2int(bits))

self.register = self._lookup_table[ba2int(bits ^ self.register)] ^ (
self.register << self._config.width_bits
)
feed_width = self._config.feed_width_bits
if len(bits) == feed_width:
table_index: int = ba2int(bits) ^ (
ba2int(self.register) >> (self._config.width_bits - feed_width)
)
self.register = self._lookup_table[table_index] ^ (
self.register << feed_width
)
else:
super()._process_bits(bits)
return self.register


Expand All @@ -254,11 +270,12 @@ def bits_create_lookup_table(width_bits: int, polynomial: int):
:parma int polynomial: which is used for the crc calculation.
"""
config = BitCrcConfiguration(width_bits=width_bits, polynomial=polynomial)
feed_width = config.feed_width_bits
crc_register = BitCrcRegister(config)
lookup_table = []
for index in range(0, 1 << width_bits):
for index in range(0, 1 << feed_width):
crc_register.init()
data = int2ba(index, length=width_bits)
data = int2ba(index, length=feed_width)
crc_register.update(data)
lookup_table.append(crc_register.digest())
return lookup_table
Expand Down
12 changes: 6 additions & 6 deletions okdmr/tests/dmrlib/etsi/crc/test_crc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@


def test_ccit_bitcrc_crc():
crc_ccit = CrcCalculator(table_based=False, configuration=Crc16.CCITT)
crc_ccit = CrcCalculator(table_based=True, configuration=Crc16.CCITT)
bit_crc_ccit = BitCrcCalculator(
table_based=False,
table_based=True,
configuration=BitCrcConfiguration(
width_bits=16,
polynomial=0x1021,
Expand All @@ -20,7 +20,7 @@ def test_ccit_bitcrc_crc():
),
)

data_bytes: bytes = b"\xFF\xEE\xAA\x88\x44\x00"
data_bytes: bytes = b"\xFF\xEE\xAA\x88\x44"
data_bits: bitarray = bytes_to_bits(data_bytes)

assert crc_ccit.calculate_checksum(data_bytes) == ba2int(
Expand All @@ -29,9 +29,9 @@ def test_ccit_bitcrc_crc():


def test_crc32_bitcrc_crc():
crc32 = CrcCalculator(table_based=False, configuration=Crc32.CRC32)
crc32 = CrcCalculator(table_based=True, configuration=Crc32.CRC32)
bit_crc32 = BitCrcCalculator(
table_based=False,
table_based=True,
configuration=BitCrcConfiguration(
width_bits=32,
polynomial=0x04C11DB7,
Expand All @@ -42,7 +42,7 @@ def test_crc32_bitcrc_crc():
),
)

data_bytes: bytes = b"\xAA\x88\x44\x00\x00\x00"
data_bytes: bytes = b"\xAA\x88\x44\x00\x00"
data_bits: bitarray = bytes_to_bits(data_bytes)

assert crc32.calculate_checksum(data_bytes) == ba2int(
Expand Down
4 changes: 2 additions & 2 deletions okdmr/tests/dmrlib/etsi/crc/test_crc9.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ def test_crc9_table():
with_table: BitCrcCalculator = BitCrcCalculator(
table_based=True, configuration=Crc9.ETSI_DMR
)
for idx in range(0, 1 << 9):
test_data = int2ba(idx, length=9)
for idx in range(1 << 9, 1 << 10):
test_data = int2ba(idx, length=10)
assert no_table.calculate_checksum(test_data) == with_table.calculate_checksum(
test_data
)

0 comments on commit 840291e

Please sign in to comment.