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 ===