update rtlsdr reader

This commit is contained in:
Junzi Sun
2020-02-14 17:53:56 +01:00
parent b60b31d4fb
commit e52d43f963
+40 -25
View File
@@ -3,88 +3,105 @@ import pyModeS as pms
from rtlsdr import RtlSdr from rtlsdr import RtlSdr
import time import time
modes_sample_rate = 2e6 sampling_rate = 2e6
smaples_per_microsec = 2
modes_frequency = 1090e6 modes_frequency = 1090e6
buffer_size = 1024 * 100 buffer_size = 1024 * 100
read_size = 1024 * 20 read_size = 1024 * 10
pbits = 8 pbits = 8
fbits = 112 fbits = 112
preamble = [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0] preamble = [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
th_amp = 0.2 # signal amplitude threshold for 0 and 1 bit # th_amp = 0.2 # signal amplitude threshold for 0 and 1 bit
th_amp_diff = 0.8 # signal amplitude threshold difference between 0 and 1 bit th_amp_diff = 0.8 # signal amplitude threshold difference between 0 and 1 bit
class RtlReader(object): class RtlReader(object):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super(RtlReader, self).__init__() super(RtlReader, self).__init__()
self.signal_buffer = [] self.signal_buffer = [] # amplitude of the sample only
self.sdr = RtlSdr() self.sdr = RtlSdr()
self.sdr.sample_rate = modes_sample_rate self.sdr.sample_rate = sampling_rate
self.sdr.center_freq = modes_frequency self.sdr.center_freq = modes_frequency
self.sdr.gain = "auto" self.sdr.gain = "auto"
# sdr.freq_correction = 75
self.debug = kwargs.get("debug", False) self.debug = kwargs.get("debug", False)
self.raw_pipe_in = None self.raw_pipe_in = None
self.stop_flag = False self.stop_flag = False
self.noise_floor = 1e6
def _calc_noise(self):
"""Calculate noise floor"""
window = smaples_per_microsec * 100
means = np.array(self.signal_buffer).reshape(-1, window).mean(axis=1)
return min(means)
def _process_buffer(self): def _process_buffer(self):
"""process raw IQ data in the buffer"""
# update noise floor
self.noise_floor = min(self._calc_noise(), self.noise_floor)
# set minimum signal amplitude
min_sig_amp = 3.162 * self.noise_floor # 10 dB SNR
# Mode S messages
messages = [] messages = []
# signal_array = np.array(self.signal_buffer)
# pulses_array = np.where(np.array(self.signal_buffer) < th_amp, 0, 1)
# pulses = "".join(str(x) for x in pulses_array)
buffer_length = len(self.signal_buffer) buffer_length = len(self.signal_buffer)
i = 0 i = 0
while i < buffer_length: while i < buffer_length:
if self.signal_buffer[i] < th_amp: if self.signal_buffer[i] < min_sig_amp:
i += 1 i += 1
continue continue
# if pulses[i : i + pbits * 2] == preamble:
if self._check_preamble(self.signal_buffer[i : i + pbits * 2]): if self._check_preamble(self.signal_buffer[i : i + pbits * 2]):
frame_start = i + pbits * 2 frame_start = i + pbits * 2
frame_end = i + pbits * 2 + (fbits + 1) * 2 frame_end = i + pbits * 2 + (fbits + 1) * 2
frame_length = (fbits + 1) * 2 frame_length = (fbits + 1) * 2
frame_pulses = self.signal_buffer[frame_start:frame_end] frame_pulses = self.signal_buffer[frame_start:frame_end]
msgbin = "" threshold = max(frame_pulses) * 0.2
msgbin = []
for j in range(0, frame_length, 2): for j in range(0, frame_length, 2):
p2 = frame_pulses[j : j + 2] p2 = frame_pulses[j : j + 2]
if len(p2) < 2: if len(p2) < 2:
break break
if p2[0] < th_amp and p2[1] < th_amp: if p2[0] < threshold and p2[1] < threshold:
break break
elif p2[0] >= p2[1]: elif p2[0] >= p2[1]:
c = "1" c = 1
elif p2[0] < p2[1]: elif p2[0] < p2[1]:
c = "0" c = 0
else: else:
msgbin = "" msgbin = []
break break
msgbin += c
msgbin.append(c)
# advance i with a jump # advance i with a jump
i = frame_start + j i = frame_start + j
if len(msgbin) > 0: if len(msgbin) > 0:
msghex = pms.bin2hex(msgbin) msghex = pms.bin2hex("".join([str(i) for i in msgbin]))
if self._check_msg(msghex): if self._check_msg(msghex):
messages.append([msghex, time.time()]) messages.append([msghex, time.time()])
if self.debug: if self.debug:
self._debug_msg(msghex) self._debug_msg(msghex)
elif i > buffer_length - 500: # elif i > buffer_length - 500:
# save some for next process # # save some for next process
break # break
else: else:
i += 1 i += 1
# keep reminder of buffer for next iteration # reset the buffer
self.signal_buffer = self.signal_buffer[i:] self.signal_buffer = self.signal_buffer[i:]
return messages return messages
def _check_preamble(self, pulses): def _check_preamble(self, pulses):
@@ -122,10 +139,8 @@ class RtlReader(object):
pass pass
def _read_callback(self, data, rtlsdr_obj): def _read_callback(self, data, rtlsdr_obj):
# scaling signal (imporatant)
amp = np.absolute(data) amp = np.absolute(data)
amp_norm = np.interp(amp, (amp.min(), amp.max()), (0, 1)) self.signal_buffer.extend(amp.tolist())
self.signal_buffer.extend(amp_norm.tolist())
if len(self.signal_buffer) >= buffer_size: if len(self.signal_buffer) >= buffer_size:
messages = self._process_buffer() messages = self._process_buffer()