diff --git a/pyModeS/decoder/common.py b/pyModeS/decoder/common.py index e6e9797..a0505c5 100644 --- a/pyModeS/decoder/common.py +++ b/pyModeS/decoder/common.py @@ -1,8 +1,6 @@ from __future__ import absolute_import, print_function, division import numpy as np - -from pyModeS.decoder import fastcrc - +from textwrap import wrap def hex2bin(hexstr): """Convert a hexdecimal string to binary string, with zero fillings.""" @@ -60,17 +58,37 @@ def crc(msg, encode=False): int: message checksum, or partity bits (encoder) """ + # the CRC generator + G = [ + int("11111111", 2), int("11111010", 2), + int("00000100", 2), int("10000000", 2) + ] + if encode: msg = msg[:-6] + "000000" - reminder_int = fastcrc.crc(msg) + msgbin = hex2bin(msg) + msgbin_split = wrap(msgbin, 8) + mbytes = list(map(bin2int, msgbin_split)) + + for ibyte in range(len(mbytes)-3): + for ibit in range(8): + mask = 0x80 >> ibit + bits = mbytes[ibyte] & mask - return reminder_int + if bits > 0: + mbytes[ibyte] = mbytes[ibyte] ^ (G[0] >> ibit) + mbytes[ibyte+1] = mbytes[ibyte+1] ^ (0xFF & ((G[0] << 8-ibit) | (G[1] >> ibit))) + mbytes[ibyte+2] = mbytes[ibyte+2] ^ (0xFF & ((G[1] << 8-ibit) | (G[2] >> ibit))) + mbytes[ibyte+3] = mbytes[ibyte+3] ^ (0xFF & ((G[2] << 8-ibit) | (G[3] >> ibit))) + result = (mbytes[-3] << 16) | (mbytes[-2] << 8) | mbytes[-1] -def crc_legacy(msg, encode=False): - """Mode-S Cyclic Redundancy Check. (Legacy code, slow).""" + return result + +def crc_legacy(msg, encode=False): + """Mode-S Cyclic Redundancy Check. (Legacy code, 2x slow).""" # 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) diff --git a/pyModeS/decoder/fastcrc.py b/pyModeS/decoder/fastcrc.py deleted file mode 100644 index fb36f7c..0000000 --- a/pyModeS/decoder/fastcrc.py +++ /dev/null @@ -1,47 +0,0 @@ -"""Compute CRC checksum of a hexadecimal string.""" - -GENERATOR = [ - int("11111111", 2), int("11111010", 2), - int("00000100", 2), int("10000000", 2) -] - - -class BytesWrapper: - - def __init__(self, hexstr): - self._bytes = [int(hexstr[i:i+2], 16) for i in range(0, len(hexstr), 2)] - - 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): - 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