Merge pull request #29 from alcibiade/fastcrc

FastCRC - A more efficient CRC calculation
This commit is contained in:
Junzi Sun
2019-05-27 20:38:27 +02:00
committed by GitHub
3 changed files with 68 additions and 22 deletions

View File

@@ -1,6 +1,9 @@
from __future__ import absolute_import, print_function, division
import numpy as np
from pyModeS.decoder import fastcrc
def hex2bin(hexstr):
"""Convert a hexdecimal string to binary string, with zero fillings. """
num_of_bits = len(hexstr) * 4
@@ -41,29 +44,15 @@ def crc(msg, encode=False):
msg (string): 28 bytes hexadecimal message string
encode (bool): True to encode the date only and return the checksum
Returns:
string: message checksum, or partity bits (encoder)
int: message checksum, or partity bits (encoder)
"""
# the polynominal generattor code for CRC [1111111111111010000001001]
generator = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,1])
ng = len(generator)
msgnpbin = bin2np(hex2bin(msg))
if encode:
msgnpbin[-24:] = [0] * 24
msg = msg[:-6] + "000000"
# loop all bits, except last 24 piraty bits
for i in range(len(msgnpbin)-24):
if msgnpbin[i] == 0:
continue
reminder_int = fastcrc.crc(msg)
# perform XOR, when 1
msgnpbin[i:i+ng] = np.bitwise_xor(msgnpbin[i:i+ng], generator)
# last 24 bits
reminder = np2bin(msgnpbin[-24:])
return reminder
return reminder_int
def floor(x):
@@ -92,7 +81,7 @@ def icao(msg):
if DF in (11, 17, 18):
addr = msg[2:8]
elif DF in (0, 4, 5, 16, 20, 21):
c0 = bin2int(crc(msg, encode=True))
c0 = crc(msg, encode=True)
c1 = hex2int(msg[-6:])
addr = '%06X' % (c0 ^ c1)
else:

View File

@@ -0,0 +1,45 @@
GENERATOR = [int("11111111", 2), int("11111010", 2), int("00000100", 2), int("10000000", 2)]
class BytesWrapper:
def __init__(self, hex: str):
if len(hex) % 2 == 1:
hex += '0'
self._bytes = [b for b in bytes.fromhex(hex)]
def byte_count(self):
return len(self._bytes) - 3
def get_bit(self, byte_index, bit_index):
mask = 0x80 >> bit_index
bits = self._bytes[byte_index] & mask
return 0 if bits == 0 else 1
def apply_matrix(self, byte_index, bit_index):
self._bytes[byte_index] = self._bytes[byte_index] ^ (GENERATOR[0] >> bit_index)
self._bytes[byte_index + 1] = self._bytes[byte_index + 1] ^ \
(0xFF & ((GENERATOR[0] << 8 - bit_index) | (GENERATOR[1] >> bit_index)))
self._bytes[byte_index + 2] = self._bytes[byte_index + 2] ^ \
(0xFF & ((GENERATOR[1] << 8 - bit_index) | (GENERATOR[2] >> bit_index)))
self._bytes[byte_index + 3] = self._bytes[byte_index + 3] ^ \
(0xFF & ((GENERATOR[2] << 8 - bit_index) | (GENERATOR[3] >> bit_index)))
def get_suffix(self) -> int:
return (self._bytes[-3] << 16) | (self._bytes[-2] << 8) | self._bytes[-1]
def crc(msg):
msgbin = BytesWrapper(msg)
for byte_index in range(msgbin.byte_count()):
for bit_index in range(8):
b = msgbin.get_bit(byte_index, bit_index)
if b == 1:
msgbin.apply_matrix(byte_index, bit_index)
result = msgbin.get_suffix()
return result