forked from adsb-related-code/mlat-server
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaltitude.py
132 lines (100 loc) · 3.51 KB
/
altitude.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# -*- mode: python; indent-tabs-mode: nil -*-
# Part of mlat-server: a Mode S multilateration server
# Copyright (C) 2015 Oliver Jowett <[email protected]>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Decoders for the 12- and 13-bit altitude encodings used in Mode S responses
and ADS-B extended squitter messages.
"""
__all__ = ('decode_ac12', 'decode_ac13')
def _decode_ac13(ac13):
if ac13 is None or ac13 == 0: # no data
return None
if ac13 & 0x0040: # M bit set
return None
if ac13 & 0x0010: # Q bit set
n = ((ac13 & 0x1f80) >> 2) | ((ac13 & 0x0020) >> 1) | (ac13 & 0x000f)
return n * 25 - 1000
# convert from Gillham code
if not (ac13 & 0x1500):
return None # illegal C bits
h = 0
if ac13 & 0x1000:
h ^= 7 # C1
if ac13 & 0x0400:
h ^= 3 # C2
if ac13 & 0x0100:
h ^= 1 # C4
if h & 5:
h ^= 5
if h > 5:
return None # illegal C bits
f = 0
if ac13 & 0x0010:
f ^= 0x1ff # D1
if ac13 & 0x0004:
f ^= 0x0ff # D2
if ac13 & 0x0001:
f ^= 0x07f # D4
if ac13 & 0x0800:
f ^= 0x03f # A1
if ac13 & 0x0200:
f ^= 0x01f # A2
if ac13 & 0x0080:
f ^= 0x00f # A4
if ac13 & 0x0020:
f ^= 0x007 # B1
if ac13 & 0x0008:
f ^= 0x003 # B2
if ac13 & 0x0002:
f ^= 0x001 # B4
if f & 1:
h = (6 - h)
a = 500 * f + 100 * h - 1300
if a < -1200:
return None # illegal value
return a
def decode_ac13(ac13):
"""Decodes a Mode S 13-bit altitude field.
The expected ordering is as specified in §3.1.2.6.5.4 of Annex 10:
C1, A1, C2, A2, C4, A4, (M), B1, (Q), B2, D2, B4, D4
Returns signed altitude in feet, or None if not decodable.
"""
if ac13 is None:
return None
return _alt_table[ac13 & 0x1fff]
def decode_ac12(ac12):
"""Decode a 12-bit AC altitude field from an extended squitter.
The expected ordering is as specified in Doc 9871 Table A-2-5:
the altitude code (AC) as specified in §3.1.2.6.5.4 of Annex 10,
but with the M-bit removed
Returns signed altitude in feet, or None if not a valid altitude."""
if ac12 is None:
return None
return _alt_table[((ac12 & 0x0fc0) << 1) | (ac12 & 0x003f)]
def _make_table():
# precompute the lookup table
return [_decode_ac13(i) for i in range(2**13)]
if __name__ == '__main__':
_alt_table = _make_table()
print('# -*- mode: python; indent-tabs-mode: nil -*-')
print('# generated by modes.altitude: python3 -m modes.altitude')
print()
print('table = (')
for i in range(0, 2**13, 8):
print(' ' + ''.join(['{0:8s}'.format(repr(a)+', ') for a in _alt_table[i:i+8]]))
print(')')
else:
try:
from .altitude_lookup import table as _alt_table
except ImportError:
_alt_table = _make_table()