Features:

- initial support for multiples tracks simulation

Enhancements:
- code profiling and optimization
 - faster lookup table based ppm + IQ generation
 - faster CRC24 computations
 - frame encoding

Bug fixes:
- callsign encoding
- typos
This commit is contained in:
Mathieu Peyréga
2022-03-15 20:23:40 +01:00
parent 5642c6564e
commit bc9687feb9
21 changed files with 645 additions and 292 deletions

View File

@@ -1,23 +1,39 @@
""" This class is responsible for low level encoding of IQ sample
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 <http://www.gnu.org/licenses/>.
"""
from CustomDecorators import *
import numpy
@Singleton
class ADSBLowLevelEncoder:
"""
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 __init__(self):
self.adsb_frame_preamble = [0xA1,0x40]
self.adsb_frame_pause = [0]*70
self._adsb_frame_preamble = [0xA1,0x40]
self._adsb_frame_pause = [0]*4
# Build a manchester encoding lookup table
self._manchester_lookup = []
for i in range(256):
me = self.manchester_encode(i)
self._manchester_lookup.append([127*val for pair in zip(me, me) for val in pair])
# Build preamble and pause manchester encoded versions
me_bits = numpy.unpackbits(numpy.asarray(self._adsb_frame_preamble, dtype=numpy.uint8))
self._adsb_frame_preamble_IQ = [127*val for pair in zip(me_bits, me_bits) for val in pair]
self._adsb_frame_pause_IQ = self._adsb_frame_pause*16
self._len_pre_IQ = len(self._adsb_frame_preamble_IQ)
self._len_pause_IQ = len(self._adsb_frame_pause_IQ)
###############################################################
# Further work on fork
# Copyright (C) 2017 David Robinson
@@ -38,65 +54,62 @@ class ADSBLowLevelEncoder:
# Encode byte
for i in range(7, -1, -1):
if self.extract_bit(byte, i):
manchester_encoded.extend([0,1])
else:
manchester_encoded.extend([1,0])
else:
manchester_encoded.extend([0,1])
return manchester_encoded
def frame_1090es_ppm_modulate(self, even, odd = []):
def frame_1090es_ppm_modulate_IQ(self, even, odd = []):
"""
Args:
even and odd: The data frames that need to be converted to PPM
Returns:
The bytearray of the PPM data
The bytearray of the IQ samples for PPM modulated data
"""
ppm = [ ]
length_even = len(even)
length_odd = len(odd)
if (length_even != 0 and length_odd == 0):
IQ = bytearray(32*length_even+2*self._len_pause_IQ+self._len_pre_IQ)
pos = self._len_pause_IQ
IQ[pos:pos+self._len_pre_IQ] = self._adsb_frame_preamble_IQ
pos += self._len_pre_IQ
if (length_even != 0):
ppm.extend(self.adsb_frame_pause) # pause
ppm.extend(self.adsb_frame_preamble) # preamble
tmp = []
for b in even:
tmp.extend(self._manchester_lookup[b])
IQ[pos:pos+32*length_even] = tmp
for i in range(length_even):
word16 = numpy.packbits(self.manchester_encode(~even[i]))
ppm.extend(word16[0:2])
ppm.extend(self.adsb_frame_pause) # pause
return IQ
if (length_odd != 0):
ppm.extend(self.adsb_frame_pause) # pause
ppm.extend(self.adsb_frame_preamble) # preamble
elif (length_even != 0 and length_odd != 0):
IQ = bytearray(32*(length_even+length_odd)+2*self._len_pre_IQ+3*self._len_pause_IQ)
pos = self._len_pause_IQ
IQ[pos:pos+self._len_pre_IQ] = self._adsb_frame_preamble_IQ
pos += self._len_pre_IQ
for i in range(length_odd):
word16 = numpy.packbits(self.manchester_encode(~odd[i]))
ppm.extend(word16[0:2])
tmp = []
for b in even:
tmp.extend(self._manchester_lookup[b])
length_even_IQ = 32*length_even
IQ[pos:pos+length_even_IQ] = tmp
pos += length_even_IQ
ppm.extend(self.adsb_frame_pause) # pause
pos += self._len_pause_IQ
IQ[pos:pos+self._len_pre_IQ] = self._adsb_frame_preamble_IQ
pos += self._len_pre_IQ
tmp = []
for b in odd:
tmp.extend(self._manchester_lookup[b])
IQ[pos:pos+32*length_odd] = tmp
return bytearray(ppm)
return IQ
def hackrf_raw_IQ_format(self, ppm):
"""
Args:
ppm: this is some data in ppm (pulse position modulation) which will be converted into
hackRF raw IQ sample format, ready to be broadcasted
Returns:
bytearray: containing the IQ data
"""
signal = []
bits = numpy.unpackbits(numpy.asarray(ppm, dtype=numpy.uint8))
for bit in bits:
if bit == 1:
I = 127
Q = 127
else:
I = 0
Q = 0
signal.append(I)
signal.append(Q)
else:
return bytearray(signal)
return None