From 960a69797627824b971e58f3b607f6177ef14b28 Mon Sep 17 00:00:00 2001 From: nzkarit Date: Tue, 5 Sep 2017 21:35:26 +1200 Subject: [PATCH] Moving code around to help my understanding. file names most probably wrong right now but will update when understand it better --- ADSB_Encoder.py | 239 +----------------------------------------------- conversions.py | 59 ++++++++++++ encoder.py | 42 +++++++++ location.py | 89 ++++++++++++++++++ parity.py | 49 ++++++++++ 5 files changed, 243 insertions(+), 235 deletions(-) create mode 100644 conversions.py create mode 100644 encoder.py create mode 100644 location.py create mode 100644 parity.py diff --git a/ADSB_Encoder.py b/ADSB_Encoder.py index 9c83746..c5c6cc8 100755 --- a/ADSB_Encoder.py +++ b/ADSB_Encoder.py @@ -1,250 +1,19 @@ #!/usr/bin/env python # -########################################################################## +from encoder import * +from location import * +from conversions import * +from parity import * -# Copyright 2010, 2012 Nick Foster -# -# This file is part of gr-air-modes -# -# gr-air-modes is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# gr-air-modes is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with gr-air-modes; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -import math - -def encode_alt_modes(alt, bit13): - mbit = False - qbit = True - encalt = (int(alt) + 1000) / 25 - - if bit13 is True: - tmp1 = (encalt & 0xfe0) << 2 - tmp2 = (encalt & 0x010) << 1 - - else: - tmp1 = (encalt & 0xff8) << 1 - tmp2 = 0 - - return (encalt & 0x0F) | tmp1 | tmp2 | (mbit << 6) | (qbit << 4) - -latz = 15 - -def nz(ctype): - return 4 * latz - ctype - -def dlat(ctype, surface): - if surface == 1: - tmp = 90.0 - else: - tmp = 360.0 - - nzcalc = nz(ctype) - if nzcalc == 0: - return tmp - else: - return tmp / nzcalc - -def nl(declat_in): - if abs(declat_in) >= 87.0: - return 1.0 - return math.floor( (2.0*math.pi) * math.acos(1.0- (1.0-math.cos(math.pi/(2.0*latz))) / math.cos( (math.pi/180.0)*abs(declat_in) )**2 )**-1) - -def dlon(declat_in, ctype, surface): - if surface: - tmp = 90.0 - else: - tmp = 360.0 - nlcalc = max(nl(declat_in)-ctype, 1) - return tmp / nlcalc - -#encode CPR position -def cpr_encode(lat, lon, ctype, surface): - if surface is True: - scalar = 2.**19 - else: - scalar = 2.**17 - - #encode using 360 constant for segment size. - dlati = dlat(ctype, False) - yz = math.floor(scalar * ((lat % dlati)/dlati) + 0.5) - rlat = dlati * ((yz / scalar) + math.floor(lat / dlati)) - - #encode using 360 constant for segment size. - dloni = dlon(lat, ctype, False) - xz = math.floor(scalar * ((lon % dloni)/dloni) + 0.5) - - yz = int(yz) & (2**17-1) - xz = int(xz) & (2**17-1) - - return (yz, xz) #lat, lon - -############################################################### - -# Copyright (C) 2015 Junzi Sun (TU Delft) - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# the polynominal generattor code for CRC -GENERATOR = "1111111111111010000001001" - -def hex2bin(hexstr): - """Convert a hexdecimal string to binary string, with zero fillings. """ - scale = 16 - num_of_bits = len(hexstr) * math.log(scale, 2) - binstr = bin(int(hexstr, scale))[2:].zfill(int(num_of_bits)) - return binstr - -def bin2int(binstr): - """Convert a binary string to integer. """ - return int(binstr, 2) - -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 ############################################################### -''' - Copyright 2015 Wolfgang Nagele - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -''' -def bin2dec(buf): - if 0 == len(buf): # Crap input - return -1 - return int(buf, 2) - -# Ported from: http://www.radarspotters.eu/forum/index.php?topic=5617.msg41293#msg41293 -def get_parity(msg, extended): - msg_length = len(msg) - payload = msg[:msg_length - 24] - parity = msg[msg_length - 24:] - - data = bin2dec(payload[0:32]) - if extended: - data1 = bin2dec(payload[32:64]) - data2 = bin2dec(payload[64:]) << 8 - - hex_id = bin2dec(parity) << 8 - - for i in range(0, len(payload)): - if ((data & 0x80000000) != 0): - data ^= 0xFFFA0480 - data <<= 1 - - if extended: - if ((data1 & 0x80000000) != 0): - data |= 1 - data1 <<= 1 - - if ((data2 & 0x80000000) != 0): - data1 = data1 | 1 - data2 <<= 1 - - return data - #return (data ^ hex_id) >> 8 ############################################################### -""" -Hamming and Manchester Encoding example -Author: Joel Addison -Date: March 2013 - -Functions to do (7,4) hamming encoding and decoding, including error detection -and correction. -Manchester encoding and decoding is also included, and by default will use -least bit ordering for the byte that is to be included in the array. -""" - -def extract_bit(byte, pos): - """ - Extract a bit from a given byte using MS ordering. - ie. B7 B6 B5 B4 B3 B2 B1 B0 - """ - return (byte >> pos) & 0x01 - -def manchester_encode(byte): - """ - Encode a byte using Manchester encoding. Returns an array of bits. - Adds two start bits (1, 1) and one stop bit (0) to the array. - """ - # Add start bits (encoded 1, 1) - # manchester_encoded = [0, 1, 0, 1] - manchester_encoded = [] - - # Encode byte - for i in range(7, -1, -1): - if extract_bit(byte, i): - manchester_encoded.append(0) - manchester_encoded.append(1) - else: - manchester_encoded.append(1) - manchester_encoded.append(0) - - # Add stop bit (encoded 0) - # manchester_encoded.append(1) - # manchester_encoded.append(0) - - return manchester_encoded ############################################################### diff --git a/conversions.py b/conversions.py new file mode 100644 index 0000000..b5ca69f --- /dev/null +++ b/conversions.py @@ -0,0 +1,59 @@ +############################################################### + +# Copyright (C) 2015 Junzi Sun (TU Delft) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# the polynominal generattor code for CRC +import math + +GENERATOR = "1111111111111010000001001" + +def hex2bin(hexstr): + """Convert a hexdecimal string to binary string, with zero fillings. """ + scale = 16 + num_of_bits = len(hexstr) * math.log(scale, 2) + binstr = bin(int(hexstr, scale))[2:].zfill(int(num_of_bits)) + return binstr + +def bin2int(binstr): + """Convert a binary string to integer. """ + return int(binstr, 2) + +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/encoder.py b/encoder.py new file mode 100644 index 0000000..98af943 --- /dev/null +++ b/encoder.py @@ -0,0 +1,42 @@ +""" +Hamming and Manchester Encoding example + +Author: Joel Addison +Date: March 2013 + +Functions to do (7,4) hamming encoding and decoding, including error detection +and correction. +Manchester encoding and decoding is also included, and by default will use +least bit ordering for the byte that is to be included in the array. +""" + +def extract_bit(byte, pos): + """ + Extract a bit from a given byte using MS ordering. + ie. B7 B6 B5 B4 B3 B2 B1 B0 + """ + return (byte >> pos) & 0x01 + +def manchester_encode(byte): + """ + Encode a byte using Manchester encoding. Returns an array of bits. + Adds two start bits (1, 1) and one stop bit (0) to the array. + """ + # Add start bits (encoded 1, 1) + # manchester_encoded = [0, 1, 0, 1] + manchester_encoded = [] + + # Encode byte + for i in range(7, -1, -1): + if extract_bit(byte, i): + manchester_encoded.append(0) + manchester_encoded.append(1) + else: + manchester_encoded.append(1) + manchester_encoded.append(0) + + # Add stop bit (encoded 0) + # manchester_encoded.append(1) + # manchester_encoded.append(0) + + return manchester_encoded diff --git a/location.py b/location.py new file mode 100644 index 0000000..b6068b7 --- /dev/null +++ b/location.py @@ -0,0 +1,89 @@ +########################################################################## + +# Copyright 2010, 2012 Nick Foster +# +# This file is part of gr-air-modes +# +# gr-air-modes is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# gr-air-modes is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with gr-air-modes; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import math + +def encode_alt_modes(alt, bit13): + mbit = False + qbit = True + encalt = (int(alt) + 1000) / 25 + + if bit13 is True: + tmp1 = (encalt & 0xfe0) << 2 + tmp2 = (encalt & 0x010) << 1 + + else: + tmp1 = (encalt & 0xff8) << 1 + tmp2 = 0 + + return (encalt & 0x0F) | tmp1 | tmp2 | (mbit << 6) | (qbit << 4) + +latz = 15 + +def nz(ctype): + return 4 * latz - ctype + +def dlat(ctype, surface): + if surface == 1: + tmp = 90.0 + else: + tmp = 360.0 + + nzcalc = nz(ctype) + if nzcalc == 0: + return tmp + else: + return tmp / nzcalc + +def nl(declat_in): + if abs(declat_in) >= 87.0: + return 1.0 + return math.floor( (2.0*math.pi) * math.acos(1.0- (1.0-math.cos(math.pi/(2.0*latz))) / math.cos( (math.pi/180.0)*abs(declat_in) )**2 )**-1) + +def dlon(declat_in, ctype, surface): + if surface: + tmp = 90.0 + else: + tmp = 360.0 + nlcalc = max(nl(declat_in)-ctype, 1) + return tmp / nlcalc + +#encode CPR position +def cpr_encode(lat, lon, ctype, surface): + if surface is True: + scalar = 2.**19 + else: + scalar = 2.**17 + + #encode using 360 constant for segment size. + dlati = dlat(ctype, False) + yz = math.floor(scalar * ((lat % dlati)/dlati) + 0.5) + rlat = dlati * ((yz / scalar) + math.floor(lat / dlati)) + + #encode using 360 constant for segment size. + dloni = dlon(lat, ctype, False) + xz = math.floor(scalar * ((lon % dloni)/dloni) + 0.5) + + yz = int(yz) & (2**17-1) + xz = int(xz) & (2**17-1) + + return (yz, xz) #lat, lon diff --git a/parity.py b/parity.py new file mode 100644 index 0000000..b7d1112 --- /dev/null +++ b/parity.py @@ -0,0 +1,49 @@ +''' + Copyright 2015 Wolfgang Nagele + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +''' +def bin2dec(buf): + if 0 == len(buf): # Crap input + return -1 + return int(buf, 2) + +# Ported from: http://www.radarspotters.eu/forum/index.php?topic=5617.msg41293#msg41293 +def get_parity(msg, extended): + msg_length = len(msg) + payload = msg[:msg_length - 24] + parity = msg[msg_length - 24:] + + data = bin2dec(payload[0:32]) + if extended: + data1 = bin2dec(payload[32:64]) + data2 = bin2dec(payload[64:]) << 8 + + hex_id = bin2dec(parity) << 8 + + for i in range(0, len(payload)): + if ((data & 0x80000000) != 0): + data ^= 0xFFFA0480 + data <<= 1 + + if extended: + if ((data1 & 0x80000000) != 0): + data |= 1 + data1 <<= 1 + + if ((data2 & 0x80000000) != 0): + data1 = data1 | 1 + data2 <<= 1 + + return data + #return (data ^ hex_id) >> 8