From 1ccd4fd83bc04ca21736927b8eb674cb7dbdf2e4 Mon Sep 17 00:00:00 2001 From: junzis Date: Wed, 23 Mar 2016 11:35:20 +0100 Subject: [PATCH] update CRC function --- pyModeS/adsb.py | 31 +------------------------ pyModeS/ehs.py | 26 ++------------------- pyModeS/util.py | 62 ++++++++++++++++++++++++------------------------- tests/run.py | 16 +++++++++++++ 4 files changed, 50 insertions(+), 85 deletions(-) diff --git a/pyModeS/adsb.py b/pyModeS/adsb.py index d089780..fdb5d27 100644 --- a/pyModeS/adsb.py +++ b/pyModeS/adsb.py @@ -19,36 +19,7 @@ along with this program. If not, see . import math import util - - -def checksum(msg): - """CRC check the ADS-B message - Args: - msg (string): 28 bytes hexadecimal message string - Returns: - bool: Checksum passed or not - """ - if len(msg) == 28: - offset = 0 - elif len(msg) == 14: - offset = 112-56 - else: - # raise exception - return False - - msgbin = util.hex2bin(msg) - checksum = int(msg[22:28], 16) - - crc = 0 - for i in xrange(len(msgbin)): - # print msgbin[i] - if int(msgbin[i]): - crc ^= util.MODES_CHECKSUM_TABLE[i+offset] - - if crc == checksum: - return True - else: - return False +from util import crc def df(msg): diff --git a/pyModeS/ehs.py b/pyModeS/ehs.py index 384068f..b3ec58f 100644 --- a/pyModeS/ehs.py +++ b/pyModeS/ehs.py @@ -18,29 +18,7 @@ along with this program. If not, see . """ import util - - -def crc(msg): - """Calculate the cyclic redundancy checksum of an message - Args: - msg (String): 28 or 14 bytes hexadecimal message string - Returns: - int: checksum in integer - """ - if len(msg) == 28: - offset = 0 - elif len(msg) == 14: - offset = 112-56 - else: - raise RuntimeError("wrong message length, need to be 28 or 14 bytes") - - msgbin = util.hex2bin(msg) - - crc = 0 - for i in xrange(len(msgbin)): - if int(msgbin[i]): - crc ^= util.MODES_CHECKSUM_TABLE[i+offset] - return crc +from util import crc def df(msg): @@ -71,7 +49,7 @@ def icao(msg): # raise RuntimeError("Message DF must be in (4, 5, 20, 21)") return None - c0 = crc(msg) + c0 = util.bin2int(crc(msg, encode=True)) c1 = util.hex2int(msg[-6:]) icao = '%06X' % (c0 ^ c1) return icao diff --git a/pyModeS/util.py b/pyModeS/util.py index c98824a..e891ac2 100644 --- a/pyModeS/util.py +++ b/pyModeS/util.py @@ -19,36 +19,8 @@ along with this program. If not, see . import math -MODES_CHECKSUM_TABLE = [ - 0x3935ea, 0x1c9af5, 0xf1b77e, 0x78dbbf, - 0xc397db, 0x9e31e9, 0xb0e2f0, 0x587178, - 0x2c38bc, 0x161c5e, 0x0b0e2f, 0xfa7d13, - 0x82c48d, 0xbe9842, 0x5f4c21, 0xd05c14, - 0x682e0a, 0x341705, 0xe5f186, 0x72f8c3, - 0xc68665, 0x9cb936, 0x4e5c9b, 0xd8d449, - 0x939020, 0x49c810, 0x24e408, 0x127204, - 0x093902, 0x049c81, 0xfdb444, 0x7eda22, - 0x3f6d11, 0xe04c8c, 0x702646, 0x381323, - 0xe3f395, 0x8e03ce, 0x4701e7, 0xdc7af7, - 0x91c77f, 0xb719bb, 0xa476d9, 0xadc168, - 0x56e0b4, 0x2b705a, 0x15b82d, 0xf52612, - 0x7a9309, 0xc2b380, 0x6159c0, 0x30ace0, - 0x185670, 0x0c2b38, 0x06159c, 0x030ace, - 0x018567, 0xff38b7, 0x80665f, 0xbfc92b, - 0xa01e91, 0xaff54c, 0x57faa6, 0x2bfd53, - 0xea04ad, 0x8af852, 0x457c29, 0xdd4410, - 0x6ea208, 0x375104, 0x1ba882, 0x0dd441, - 0xf91024, 0x7c8812, 0x3e4409, 0xe0d800, - 0x706c00, 0x383600, 0x1c1b00, 0x0e0d80, - 0x0706c0, 0x038360, 0x01c1b0, 0x00e0d8, - 0x00706c, 0x003836, 0x001c1b, 0xfff409, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000 -] +# the polynominal generattor code for CRC +GENERATOR = "1111111111111010000001001" def hex2bin(hexstr): @@ -70,4 +42,32 @@ def hex2int(hexstr): def df(msg): """Decode Downlink Format vaule, bits 1 to 5.""" msgbin = hex2bin(msg) - return bin2int(msgbin[0: 5]) + return bin2int(msgbin[0:5]) + + +def crc(msg, encode=False): + """Mode-S Cyclic Redundancy Check + Detect if bit error occurs in the Mode-S message + Args: + 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) + """ + + msgbin = list(hex2bin(msg)) + + if encode: + msgbin[-24:] = ['0'] * 24 + + # loop all bits, except last 24 piraty bits + for i in range(len(msgbin)-24): + # if 1, perform modulo 2 multiplication, + if msgbin[i] == '1': + for j in range(len(GENERATOR)): + # modulo 2 multiplication = XOR + msgbin[i+j] = str((int(msgbin[i+j]) ^ int(GENERATOR[j]))) + + # last 24 bits + reminder = ''.join(msgbin[-24:]) + return reminder diff --git a/tests/run.py b/tests/run.py index 99353dd..60fa629 100644 --- a/tests/run.py +++ b/tests/run.py @@ -7,6 +7,22 @@ sys.path.insert(0, parentdir) import pyModeS as pms from pyModeS import adsb from pyModeS import ehs +from pyModeS import util + + +# === TEST common functions === +def test_hex2bin(): + assert util.hex2bin('6E406B') == "011011100100000001101011" + + +def test_crc(): + # crc decoder + checksum = util.crc("8D406B902015A678D4D220AA4BDA") + assert checksum == "000000000000000000000000" + + # crc encoder + parity = util.crc("8D406B902015A678D4D220AA4BDA", encode=True) + assert util.hex2bin("AA4BDA") == parity # === TEST ADS-B package ===