Merge pull request #29 from alcibiade/fastcrc
FastCRC - A more efficient CRC calculation
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
from __future__ import absolute_import, print_function, division
|
from __future__ import absolute_import, print_function, division
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
from pyModeS.decoder import fastcrc
|
||||||
|
|
||||||
|
|
||||||
def hex2bin(hexstr):
|
def hex2bin(hexstr):
|
||||||
"""Convert a hexdecimal string to binary string, with zero fillings. """
|
"""Convert a hexdecimal string to binary string, with zero fillings. """
|
||||||
num_of_bits = len(hexstr) * 4
|
num_of_bits = len(hexstr) * 4
|
||||||
@@ -41,29 +44,15 @@ def crc(msg, encode=False):
|
|||||||
msg (string): 28 bytes hexadecimal message string
|
msg (string): 28 bytes hexadecimal message string
|
||||||
encode (bool): True to encode the date only and return the checksum
|
encode (bool): True to encode the date only and return the checksum
|
||||||
Returns:
|
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:
|
if encode:
|
||||||
msgnpbin[-24:] = [0] * 24
|
msg = msg[:-6] + "000000"
|
||||||
|
|
||||||
# loop all bits, except last 24 piraty bits
|
reminder_int = fastcrc.crc(msg)
|
||||||
for i in range(len(msgnpbin)-24):
|
|
||||||
if msgnpbin[i] == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# perform XOR, when 1
|
return reminder_int
|
||||||
msgnpbin[i:i+ng] = np.bitwise_xor(msgnpbin[i:i+ng], generator)
|
|
||||||
|
|
||||||
# last 24 bits
|
|
||||||
reminder = np2bin(msgnpbin[-24:])
|
|
||||||
return reminder
|
|
||||||
|
|
||||||
|
|
||||||
def floor(x):
|
def floor(x):
|
||||||
@@ -92,7 +81,7 @@ def icao(msg):
|
|||||||
if DF in (11, 17, 18):
|
if DF in (11, 17, 18):
|
||||||
addr = msg[2:8]
|
addr = msg[2:8]
|
||||||
elif DF in (0, 4, 5, 16, 20, 21):
|
elif DF in (0, 4, 5, 16, 20, 21):
|
||||||
c0 = bin2int(crc(msg, encode=True))
|
c0 = crc(msg, encode=True)
|
||||||
c1 = hex2int(msg[-6:])
|
c1 = hex2int(msg[-6:])
|
||||||
addr = '%06X' % (c0 ^ c1)
|
addr = '%06X' % (c0 ^ c1)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -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
|
||||||
+15
-3
@@ -5,12 +5,24 @@ def test_hex2bin():
|
|||||||
assert common.hex2bin('6E406B') == "011011100100000001101011"
|
assert common.hex2bin('6E406B') == "011011100100000001101011"
|
||||||
|
|
||||||
def test_crc_decode():
|
def test_crc_decode():
|
||||||
checksum = common.crc("8D406B902015A678D4D220AA4BDA")
|
assert common.crc("8D406B902015A678D4D220AA4BDA") == 0
|
||||||
assert checksum == "000000000000000000000000"
|
assert common.crc('8d8960ed58bf053cf11bc5932b7d') == 0
|
||||||
|
assert common.crc('8d45cab390c39509496ca9a32912') == 0
|
||||||
|
assert common.crc('8d49d3d4e1089d00000000744c3b') == 0
|
||||||
|
assert common.crc('8d74802958c904e6ef4ba0184d5c') == 0
|
||||||
|
assert common.crc('8d4400cd9b0000b4f87000e71a10') == 0
|
||||||
|
assert common.crc('8d4065de58a1054a7ef0218e226a') == 0
|
||||||
|
|
||||||
|
assert common.crc('c80b2dca34aa21dd821a04cb64d4') == 10719924
|
||||||
|
assert common.crc('a800089d8094e33a6004e4b8a522') == 4805588
|
||||||
|
assert common.crc('a8000614a50b6d32bed000bbe0ed') == 5659991
|
||||||
|
assert common.crc('a0000410bc900010a40000f5f477') == 11727682
|
||||||
|
assert common.crc('8d4ca251204994b1c36e60a5343d') == 16
|
||||||
|
assert common.crc('b0001718c65632b0a82040715b65') == 353333
|
||||||
|
|
||||||
def test_crc_encode():
|
def test_crc_encode():
|
||||||
parity = common.crc("8D406B902015A678D4D220AA4BDA", encode=True)
|
parity = common.crc("8D406B902015A678D4D220AA4BDA", encode=True)
|
||||||
assert common.hex2bin("AA4BDA") == parity
|
assert int("AA4BDA", 16) == parity
|
||||||
|
|
||||||
def test_icao():
|
def test_icao():
|
||||||
assert common.icao("8D406B902015A678D4D220AA4BDA") == "406B90"
|
assert common.icao("8D406B902015A678D4D220AA4BDA") == "406B90"
|
||||||
|
|||||||
Reference in New Issue
Block a user