kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Switch iMet-1/4 decoder to IQ input.
rodzic
7fb25745f2
commit
17894c5ecc
|
@ -162,9 +162,13 @@ def start_scanner():
|
|||
detect_dwell_time=config["detect_dwell_time"],
|
||||
max_peaks=config["max_peaks"],
|
||||
rs_path=RS_PATH,
|
||||
sdr_power=config["sdr_power"],
|
||||
sdr_fm=config["sdr_fm"],
|
||||
device_idx=_device_idx,
|
||||
sdr_type=config["sdr_type"],
|
||||
# Network SDR Options
|
||||
sdr_hostname=config["sdr_hostname"],
|
||||
sdr_port=config["sdr_port"],
|
||||
rtl_power_path=config["sdr_power"],
|
||||
rtl_fm_path=config["sdr_fm"],
|
||||
rtl_device_idx=_device_idx,
|
||||
gain=autorx.sdr_list[_device_idx]["gain"],
|
||||
ppm=autorx.sdr_list[_device_idx]["ppm"],
|
||||
bias=autorx.sdr_list[_device_idx]["bias"],
|
||||
|
@ -233,11 +237,11 @@ def start_decoder(freq, sonde_type):
|
|||
autorx.task_list[freq]["task"] = SondeDecoder(
|
||||
sonde_type=sonde_type,
|
||||
sonde_freq=freq,
|
||||
sdr_type = "RTLSDR", # TODO!
|
||||
rs_path=RS_PATH,
|
||||
# Network SDR Options (TODO)
|
||||
sdr_hostname="localhost",
|
||||
sdr_port=12345,
|
||||
sdr_type=config["sdr_type"],
|
||||
# Network SDR Options
|
||||
sdr_hostname=config["sdr_hostname"],
|
||||
sdr_port=config["sdr_port"],
|
||||
# RTLSDR Options
|
||||
rtl_fm_path=config["sdr_fm"],
|
||||
rtl_device_idx=_device_idx,
|
||||
|
|
|
@ -17,7 +17,7 @@ except ImportError:
|
|||
# MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus.
|
||||
# PATCH - Small changes, or minor feature additions.
|
||||
|
||||
__version__ = "1.5.11-alpha1"
|
||||
__version__ = "1.5.11-alpha2"
|
||||
|
||||
|
||||
# Global Variables
|
||||
|
|
|
@ -11,7 +11,7 @@ import logging
|
|||
import os
|
||||
import traceback
|
||||
import json
|
||||
from .utils import rtlsdr_test
|
||||
from .sdr_wrappers import test_sdr
|
||||
|
||||
# Dummy initial config with some parameters we need to make the web interface happy.
|
||||
global_config = {
|
||||
|
@ -71,6 +71,9 @@ def read_auto_rx_config(filename, no_sdr_test=False):
|
|||
"email_to": None,
|
||||
"email_subject": "<type> Sonde launch detected on <freq>: <id>",
|
||||
# SDR Settings
|
||||
"sdr_type": "RTLSDR",
|
||||
"sdr_hostname": "localhost",
|
||||
"sdr_port": 5555,
|
||||
"sdr_fm": "rtl_fm",
|
||||
"sdr_power": "rtl_power",
|
||||
"sdr_quantity": 1,
|
||||
|
@ -685,45 +688,110 @@ def read_auto_rx_config(filename, no_sdr_test=False):
|
|||
auto_rx_config["aprs_port"] = 14590
|
||||
|
||||
|
||||
# 1.6.0 - New SDR options
|
||||
try:
|
||||
auto_rx_config["sdr_type"] = config.get("sdr", "sdr_type")
|
||||
auto_rx_config["sdr_hostname"] = config.get("sdr", "sdr_hostname")
|
||||
auto_rx_config["sdr_port"] = config.getint("sdr", "sdr_port")
|
||||
except:
|
||||
# Switch this to warning on release...
|
||||
logging.debug(
|
||||
"Config - Did not find sdr_type option, using defaults."
|
||||
)
|
||||
|
||||
|
||||
# If we are being called as part of a unit test, just return the config now.
|
||||
if no_sdr_test:
|
||||
return auto_rx_config
|
||||
|
||||
# Now we attempt to read in the individual SDR parameters.
|
||||
# Now we enumerate our SDRs.
|
||||
auto_rx_config["sdr_settings"] = {}
|
||||
|
||||
for _n in range(1, auto_rx_config["sdr_quantity"] + 1):
|
||||
_section = "sdr_%d" % _n
|
||||
try:
|
||||
_device_idx = config.get(_section, "device_idx")
|
||||
_ppm = round(config.getfloat(_section, "ppm"))
|
||||
_gain = config.getfloat(_section, "gain")
|
||||
_bias = config.getboolean(_section, "bias")
|
||||
if auto_rx_config["sdr_type"] == "RTLSDR":
|
||||
# Multiple RTLSDRs in use - we need to read in each SDRs settings.
|
||||
for _n in range(1, auto_rx_config["sdr_quantity"] + 1):
|
||||
_section = "sdr_%d" % _n
|
||||
try:
|
||||
_device_idx = config.get(_section, "device_idx")
|
||||
_ppm = round(config.getfloat(_section, "ppm"))
|
||||
_gain = config.getfloat(_section, "gain")
|
||||
_bias = config.getboolean(_section, "bias")
|
||||
|
||||
if (auto_rx_config["sdr_quantity"] > 1) and (_device_idx == "0"):
|
||||
logging.critical(
|
||||
"Config - SDR Device ID of 0 used with a multi-SDR configuration. Go read the warning in the config file!"
|
||||
if (auto_rx_config["sdr_quantity"] > 1) and (_device_idx == "0"):
|
||||
logging.critical(
|
||||
"Config - RTLSDR Device ID of 0 used with a multi-SDR configuration. Go read the warning in the config file!"
|
||||
)
|
||||
return None
|
||||
|
||||
# See if the SDR exists.
|
||||
_sdr_valid = test_sdr(sdr_type = "RTLSDR", rtl_device_idx = _device_idx)
|
||||
if _sdr_valid:
|
||||
auto_rx_config["sdr_settings"][_device_idx] = {
|
||||
"ppm": _ppm,
|
||||
"gain": _gain,
|
||||
"bias": _bias,
|
||||
"in_use": False,
|
||||
"task": None,
|
||||
}
|
||||
logging.info("Config - Tested RTLSDR #%s OK" % _device_idx)
|
||||
else:
|
||||
logging.warning("Config - RTLSDR #%s invalid." % _device_idx)
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
"Config - Error parsing RTLSDR %d config - %s" % (_n, str(e))
|
||||
)
|
||||
return None
|
||||
continue
|
||||
|
||||
# See if the SDR exists.
|
||||
_sdr_valid = rtlsdr_test(_device_idx)
|
||||
if _sdr_valid:
|
||||
auto_rx_config["sdr_settings"][_device_idx] = {
|
||||
"ppm": _ppm,
|
||||
"gain": _gain,
|
||||
"bias": _bias,
|
||||
"in_use": False,
|
||||
"task": None,
|
||||
}
|
||||
logging.info("Config - Tested SDR #%s OK" % _device_idx)
|
||||
else:
|
||||
logging.warning("Config - SDR #%s invalid." % _device_idx)
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
"Config - Error parsing SDR %d config - %s" % (_n, str(e))
|
||||
)
|
||||
continue
|
||||
elif auto_rx_config["sdr_type"] == "SpyServer":
|
||||
# Test access to the SpyServer
|
||||
_sdr_ok = test_sdr(
|
||||
sdr_type=auto_rx_config["sdr_type"],
|
||||
sdr_hostname=auto_rx_config["sdr_hostname"],
|
||||
sdr_port=auto_rx_config["sdr_port"]
|
||||
)
|
||||
|
||||
if not _sdr_ok:
|
||||
logging.critical(f"Config - Could not contact SpyServer {auto_rx_config['sdr_hostname']}:{auto_rx_config['sdr_port']}. Exiting.")
|
||||
return None
|
||||
|
||||
for _n in range(1, auto_rx_config["sdr_quantity"] + 1):
|
||||
_sdr_name = f"SPY{_n:02d}"
|
||||
auto_rx_config["sdr_settings"][_sdr_name] = {
|
||||
"ppm": 0,
|
||||
"gain": 0,
|
||||
"bias": 0,
|
||||
"in_use": False,
|
||||
"task": None,
|
||||
}
|
||||
|
||||
elif auto_rx_config["sdr_type"] == "KA9Q":
|
||||
# Test access to the SpyServer
|
||||
_sdr_ok = test_sdr(
|
||||
sdr_type=auto_rx_config["sdr_type"],
|
||||
sdr_hostname=auto_rx_config["sdr_hostname"],
|
||||
sdr_port=auto_rx_config["sdr_port"]
|
||||
)
|
||||
|
||||
if not _sdr_ok:
|
||||
logging.critical(f"Config - Could not contact KA9Q Server {auto_rx_config['sdr_hostname']}:{auto_rx_config['sdr_port']}. Exiting.")
|
||||
return None
|
||||
|
||||
for _n in range(1, auto_rx_config["sdr_quantity"] + 1):
|
||||
_sdr_name = f"KA9Q{_n:02d}"
|
||||
auto_rx_config["sdr_settings"][_sdr_name] = {
|
||||
"ppm": 0,
|
||||
"gain": 0,
|
||||
"bias": 0,
|
||||
"in_use": False,
|
||||
"task": None,
|
||||
}
|
||||
|
||||
logging.critical("Config - KA9Q SDR Support not implemented yet - exiting.")
|
||||
return None
|
||||
|
||||
else:
|
||||
logging.critical(f"Config - Unknown SDR Type {auto_rx_config['sdr_type']} - exiting.")
|
||||
return None
|
||||
|
||||
# Sanity checks when using more than one SDR
|
||||
if (len(auto_rx_config["sdr_settings"].keys()) > 1) and (
|
||||
|
|
|
@ -149,11 +149,9 @@ class SondeDecoder(object):
|
|||
|
||||
sdr_type (str): 'RTLSDR', 'Spyserver' or 'KA9Q'
|
||||
|
||||
|
||||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
sdr_port (int): Port number of KA9Q Server
|
||||
|
||||
|
||||
Arguments for RTLSDRs:
|
||||
rtl_fm_path (str): Path to rtl_fm, or drop-in equivalent. Defaults to 'rtl_fm'
|
||||
|
@ -358,28 +356,23 @@ class SondeDecoder(object):
|
|||
|
||||
if self.sonde_type == "RS41":
|
||||
# RS41 Decoder command.
|
||||
# rtl_fm -p 0 -g -1 -M fm -F9 -s 15k -f 405500000 | sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2600 2>/dev/null | ./rs41ecc --crc --ecc --ptu
|
||||
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null | " % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
)
|
||||
|
||||
# If selected by the user, we can add a highpass filter into the sox command. This helps handle up to about 5ppm of receiver drift
|
||||
# before performance becomes significantly degraded. By default this is off, as it is not required with TCXO RTLSDRs, and actually
|
||||
# slightly degrades performance.
|
||||
if self.rs41_drift_tweak:
|
||||
_highpass = "highpass 20 "
|
||||
else:
|
||||
_highpass = ""
|
||||
_sample_rate = 48000
|
||||
_filter_bandwidth = 15000
|
||||
|
||||
decode_cmd += (
|
||||
"sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - %slowpass 2600 2>/dev/null | "
|
||||
% _highpass
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_filter_bandwidth,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20,
|
||||
lowpass = 2600
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -430,20 +423,22 @@ class SondeDecoder(object):
|
|||
# No PTU data availble for RS92-NGP sondes.
|
||||
_ptu_opts = "--ngp --ptu"
|
||||
|
||||
# Now construct the decoder command.
|
||||
# rtl_fm -p 0 -g 26.0 -M fm -F9 -s 12k -f 400500000 | sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2500 2>/dev/null | ./rs92ecc -vx -v --crc --ecc --vel -e ephemeris.dat
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_rx_bw,
|
||||
self.sonde_freq,
|
||||
)
|
||||
decode_cmd += (
|
||||
"sox -t raw -r %d -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2500 highpass 20 2>/dev/null |"
|
||||
% _rx_bw
|
||||
|
||||
_sample_rate = 48000
|
||||
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_rx_bw,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20,
|
||||
lowpass = 2500
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -461,16 +456,23 @@ class SondeDecoder(object):
|
|||
# so we don't need to specify an invert flag.
|
||||
# 2019-02-27: Added the --dist flag, which should reduce bad positions a bit.
|
||||
|
||||
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
_filter_bandwidth = 15000
|
||||
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_filter_bandwidth,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20,
|
||||
lowpass = 2000
|
||||
)
|
||||
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2000 2>/dev/null |"
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
if self.save_decode_audio:
|
||||
|
@ -482,15 +484,22 @@ class SondeDecoder(object):
|
|||
elif self.sonde_type == "M10":
|
||||
# M10 Sondes
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 22k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
_filter_bandwidth = 22000
|
||||
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_filter_bandwidth,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20
|
||||
)
|
||||
decode_cmd += "sox -t raw -r 22k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
if self.save_decode_audio:
|
||||
|
@ -502,33 +511,42 @@ class SondeDecoder(object):
|
|||
elif self.sonde_type == "IMET":
|
||||
# iMet-4 Sondes
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
|
||||
decode_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
if self.save_decode_audio:
|
||||
decode_cmd += " tee decode_%s.wav |" % str(self.rtl_device_idx)
|
||||
if self.save_decode_iq:
|
||||
decode_cmd += " tee decode_%s.raw |" % str(self.rtl_device_idx)
|
||||
|
||||
# iMet-4 (IMET1RS) decoder
|
||||
decode_cmd += f"./imet1rs_dft --json {self.raw_file_option} 2>/dev/null"
|
||||
decode_cmd += f"./imet4iq --iq 0.0 --lpIQ --dc - {_sample_rate} 16 --json 2>/dev/null"
|
||||
|
||||
elif self.sonde_type == "IMET5":
|
||||
# iMet-54 Sondes
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s 48k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
|
||||
decode_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -543,22 +561,27 @@ class SondeDecoder(object):
|
|||
elif self.sonde_type == "MRZ":
|
||||
# Meteo-Radiy MRZ Sondes
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
|
||||
decode_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
if self.save_decode_audio:
|
||||
decode_cmd += " tee decode_%s.wav |" % str(self.rtl_device_idx)
|
||||
if self.save_decode_iq:
|
||||
decode_cmd += " tee decode_IQ_%s.bin |" % str(self.rtl_device_idx)
|
||||
|
||||
# MRZ decoder
|
||||
decode_cmd += "./mp3h1mod --auto --json --ptu 2>/dev/null"
|
||||
#decode_cmd += "./mp3h1mod --auto --json --ptu 2>/dev/null"
|
||||
decode_cmd += "./mp3h1mod --IQ 0.0 --lp - 48000 16 --json --ptu 2>/dev/null"
|
||||
|
||||
elif self.sonde_type == "MK2LMS":
|
||||
# 1680 MHz LMS6 sondes, using 9600 baud MK2A-format telemetry.
|
||||
|
@ -571,13 +594,21 @@ class SondeDecoder(object):
|
|||
# mk2mod runs at ~90% CPU on a RPi 3, with rtl_fm using ~50% of another core.
|
||||
# Update 2021-07-24: Updated version with speedups now taking 240 kHz BW and only using 50% of a core.
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M raw -s 240k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
|
||||
_baud_rate = 4800
|
||||
_sample_rate = 240000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
fast_filter = True
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -598,26 +629,23 @@ class SondeDecoder(object):
|
|||
# LMS6 Decoder command.
|
||||
# rtl_fm -p 0 -g -1 -M fm -F9 -s 15k -f 405500000 | sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2600 2>/dev/null | ./rs41ecc --crc --ecc --ptu
|
||||
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null | " % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
)
|
||||
|
||||
# If selected by the user, we can add a highpass filter into the sox command. This helps handle up to about 5ppm of receiver drift
|
||||
# before performance becomes significantly degraded. By default this is off, as it is not required with TCXO RTLSDRs, and actually
|
||||
# slightly degrades performance.
|
||||
if self.rs41_drift_tweak:
|
||||
_highpass = "highpass 20 "
|
||||
else:
|
||||
_highpass = ""
|
||||
_sample_rate = 48000
|
||||
_filter_bandwidth = 15000
|
||||
|
||||
decode_cmd += (
|
||||
"sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - %slowpass 2600 2>/dev/null | "
|
||||
% _highpass
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_filter_bandwidth,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20,
|
||||
lowpass = 2600
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -630,15 +658,22 @@ class SondeDecoder(object):
|
|||
# Meisei IMS-100 Sondes
|
||||
# Starting out with a 15 kHz bandwidth filter.
|
||||
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_sample_rate = 48000
|
||||
_filter_bandwidth = 15000
|
||||
|
||||
decode_cmd = get_sdr_fm_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
filter_bandwidth=_filter_bandwidth,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
highpass = 20
|
||||
)
|
||||
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 2>/dev/null |"
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
if self.save_decode_audio:
|
||||
|
@ -684,11 +719,11 @@ class SondeDecoder(object):
|
|||
# RS41 Decoder
|
||||
|
||||
_baud_rate = 4800
|
||||
_sample_rate = _baud_rate*10 # 10x Oversampling
|
||||
_sample_rate = 48000 # 10x Oversampling
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -1.0*(_sample_rate*0.20)
|
||||
_upper = (_sample_rate*0.20)
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
|
@ -749,32 +784,30 @@ class SondeDecoder(object):
|
|||
else:
|
||||
_rs92_gps_data = "-e %s" % self.rs92_ephemeris
|
||||
|
||||
if self.sonde_freq > 1000e6:
|
||||
# Use a higher IQ rate for 1680 MHz sondes, at the expense of some CPU usage.
|
||||
_sdr_rate = 96000
|
||||
_ptu_ops = "--ngp --ptu"
|
||||
else:
|
||||
# On 400 MHz, use 48 khz - RS92s dont drift far enough to need any more than this.
|
||||
_sdr_rate = 48000
|
||||
_ptu_ops = "--ptu"
|
||||
|
||||
_output_rate = 48000
|
||||
_baud_rate = 4800
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
|
||||
if self.sonde_freq > 1000e6:
|
||||
_sample_rate = 96000
|
||||
_ptu_ops = "--ngp --ptu"
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
else:
|
||||
_sample_rate = 48000
|
||||
_ptu_ops = "--ptu"
|
||||
_lower = -20000
|
||||
_upper = 20000
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -785,7 +818,7 @@ class SondeDecoder(object):
|
|||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
_sdr_rate,
|
||||
_sample_rate,
|
||||
_baud_rate,
|
||||
)
|
||||
|
||||
|
@ -796,28 +829,34 @@ class SondeDecoder(object):
|
|||
|
||||
# RS92s transmit continuously - average over the last 2 frames, and use a mean
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "DFM":
|
||||
# DFM06/DFM09 Sondes.
|
||||
# DFM06/DFM09/DFM17 Sondes.
|
||||
|
||||
_sdr_rate = 50000
|
||||
_baud_rate = 2500
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
_sample_rate = 50000 # 10x Oversampling
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
if (abs(403200000 - frequency) < 20000) and (sdr_type == "RTLSDR"):
|
||||
# Narrow up the frequency estimator window if we are close to
|
||||
# the 403.2 MHz RTLSDR Spur.
|
||||
_lower = -8000
|
||||
_upper = 8000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -828,7 +867,7 @@ class SondeDecoder(object):
|
|||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
_sdr_rate,
|
||||
_sample_rate,
|
||||
_baud_rate,
|
||||
)
|
||||
|
||||
|
@ -843,29 +882,31 @@ class SondeDecoder(object):
|
|||
|
||||
# DFM sondes transmit continuously - average over the last 2 frames, and peak hold
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "M10":
|
||||
# M10 Sondes
|
||||
# These have a 'weird' baud rate, and as fsk_demod requires the input sample rate to be an integer multiple of the baud rate,
|
||||
# our required sample rate is correspondingly weird!
|
||||
_sdr_rate = 48080
|
||||
_baud_rate = 9616
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
_baud_rate = 9616
|
||||
_sample_rate = 48080
|
||||
_p = 5 # Override the oversampling rate
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -873,8 +914,8 @@ class SondeDecoder(object):
|
|||
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.rtl_device_idx)
|
||||
|
||||
demod_cmd += (
|
||||
"./fsk_demod --cs16 -b %d -u %d -s -p 5 --stats=%d 2 %d %d - -"
|
||||
% (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
|
||||
"./fsk_demod --cs16 -b %d -u %d -s -p %d --stats=%d 2 %d %d - -"
|
||||
% (_lower, _upper, _p, _stats_rate, _sample_rate, _baud_rate)
|
||||
)
|
||||
|
||||
# M10 decoder
|
||||
|
@ -882,28 +923,30 @@ class SondeDecoder(object):
|
|||
|
||||
# M10 sondes transmit in short, irregular pulses - average over the last 2 frames, and use a peak hold
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "M20":
|
||||
# M20 Sondes
|
||||
# 9600 baud.
|
||||
_sdr_rate = 48000
|
||||
_baud_rate = 9600
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
_baud_rate = 9600
|
||||
_sample_rate = 48000
|
||||
_p = 5
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -911,8 +954,8 @@ class SondeDecoder(object):
|
|||
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.rtl_device_idx)
|
||||
|
||||
demod_cmd += (
|
||||
"./fsk_demod --cs16 -b %d -u %d -s -p 5 --stats=%d 2 %d %d - -"
|
||||
% (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
|
||||
"./fsk_demod --cs16 -b %d -u %d -s -p %d --stats=%d 2 %d %d - -"
|
||||
% (_lower, _upper, _p, _stats_rate, _sample_rate, _baud_rate)
|
||||
)
|
||||
|
||||
# M20 decoder
|
||||
|
@ -920,29 +963,30 @@ class SondeDecoder(object):
|
|||
|
||||
# M20 sondes transmit in short, irregular pulses - average over the last 2 frames, and use a peak hold
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type.startswith("LMS"):
|
||||
# LMS6 (400 MHz variant) Decoder command.
|
||||
_sdr_rate = 48000 # IQ rate. Lower rate = lower CPU usage, but less frequency tracking ability.
|
||||
_output_rate = 48000
|
||||
_baud_rate = 4800
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
_baud_rate = 4800
|
||||
_sample_rate = 48000
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
if self.save_decode_iq:
|
||||
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.rtl_device_idx)
|
||||
|
@ -951,7 +995,7 @@ class SondeDecoder(object):
|
|||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
_sdr_rate,
|
||||
_sample_rate,
|
||||
_baud_rate,
|
||||
)
|
||||
|
||||
|
@ -959,28 +1003,28 @@ class SondeDecoder(object):
|
|||
|
||||
# LMS sondes transmit continuously - average over the last 2 frames, and use a peak hold
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "IMET5":
|
||||
# iMet-54 Decoder command.
|
||||
_sdr_rate = 48000 # IQ rate. Lower rate = lower CPU usage, but less frequency tracking ability.
|
||||
_output_rate = 48000
|
||||
_baud_rate = 4800
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
_baud_rate = 4800
|
||||
_sample_rate = 48000
|
||||
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
if self.save_decode_iq:
|
||||
|
@ -990,7 +1034,7 @@ class SondeDecoder(object):
|
|||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
_sdr_rate,
|
||||
_sample_rate,
|
||||
_baud_rate,
|
||||
)
|
||||
|
||||
|
@ -998,28 +1042,28 @@ class SondeDecoder(object):
|
|||
|
||||
# iMet54 sondes transmit in bursts. Use a peak hold.
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "MRZ":
|
||||
# MRZ Sondes.
|
||||
|
||||
_sdr_rate = 48000
|
||||
_baud_rate = 2400
|
||||
_offset = 0.25 # Place the sonde frequency in the centre of the passband.
|
||||
_lower = int(
|
||||
0.025 * _sdr_rate
|
||||
) # Limit the frequency estimation window to not include the passband edges.
|
||||
_upper = int(0.475 * _sdr_rate)
|
||||
_freq = int(self.sonde_freq - _sdr_rate * _offset)
|
||||
_sample_rate = 48000
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
_sdr_rate,
|
||||
_freq,
|
||||
# Limit FSK estimator window to roughly +/- 10 kHz
|
||||
_lower = -10000
|
||||
_upper = 10000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias
|
||||
)
|
||||
|
||||
# Add in tee command to save IQ to disk if debugging is enabled.
|
||||
|
@ -1030,7 +1074,7 @@ class SondeDecoder(object):
|
|||
_lower,
|
||||
_upper,
|
||||
_stats_rate,
|
||||
_sdr_rate,
|
||||
_sample_rate,
|
||||
_baud_rate,
|
||||
)
|
||||
|
||||
|
@ -1039,7 +1083,7 @@ class SondeDecoder(object):
|
|||
|
||||
# MRZ sondes transmit continuously - average over the last frame, and use a peak hold
|
||||
demod_stats = FSKDemodStats(averaging_time=1.0, peak_hold=True)
|
||||
self.rx_frequency = _freq
|
||||
self.rx_frequency = self.sonde_freq
|
||||
|
||||
elif self.sonde_type == "MK2LMS":
|
||||
# 1680 MHz LMS6 sondes, using 9600 baud MK2A-format telemetry.
|
||||
|
@ -1051,13 +1095,20 @@ class SondeDecoder(object):
|
|||
# Have scaled back sample rate to 220 kHz to again save CPU.
|
||||
# mk2mod runs at ~90% CPU on a RPi 3, with rtl_fm using ~50% of another core.
|
||||
|
||||
demod_cmd = "%s %s-p %d -d %s %s-M raw -s 220k -f %d 2>/dev/null |" % (
|
||||
self.rtl_fm_path,
|
||||
bias_option,
|
||||
int(self.ppm),
|
||||
str(self.rtl_device_idx),
|
||||
gain_param,
|
||||
self.sonde_freq,
|
||||
_baud_rate = 4800
|
||||
_sample_rate = 220000
|
||||
|
||||
demod_cmd = get_sdr_iq_cmd(
|
||||
sdr_type = self.sdr_type,
|
||||
frequency = self.sonde_freq,
|
||||
sample_rate = _sample_rate,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
ppm = self.ppm,
|
||||
gain = self.gain,
|
||||
bias = self.bias,
|
||||
fast_filter = True # Don't use -F9
|
||||
)
|
||||
|
||||
# Add in tee command to save audio to disk if debugging is enabled.
|
||||
|
@ -1068,6 +1119,7 @@ class SondeDecoder(object):
|
|||
demod_cmd += f"./mk2mod --iq 0.0 --lpIQ --lpbw 160 --lpFM --dc --crc --json {self.raw_file_option} - 220000 16 2>/dev/null"
|
||||
decode_cmd = None
|
||||
demod_stats = None
|
||||
self.rx_frequency = self.sonde_freq
|
||||
# Settings for old decoder, which cares about FM inversion.
|
||||
# if self.inverted:
|
||||
# self.log_debug("Using inverted MK2A decoder.")
|
||||
|
@ -1511,9 +1563,14 @@ class SondeDecoder(object):
|
|||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.debug(
|
||||
"Decoder #%s %s %.3f - %s"
|
||||
% (str(self.rtl_device_idx), self.sonde_type, self.sonde_freq / 1e6, line)
|
||||
f"Decoder ({_sdr_name}) {self.sonde_type} {self.sonde_freq/1e6:.3f} - {line}"
|
||||
)
|
||||
|
||||
def log_info(self, line):
|
||||
|
@ -1521,9 +1578,14 @@ class SondeDecoder(object):
|
|||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.info(
|
||||
"Decoder #%s %s %.3f - %s"
|
||||
% (str(self.rtl_device_idx), self.sonde_type, self.sonde_freq / 1e6, line)
|
||||
f"Decoder ({_sdr_name}) {self.sonde_type} {self.sonde_freq/1e6:.3f} - {line}"
|
||||
)
|
||||
|
||||
def log_error(self, line):
|
||||
|
@ -1531,9 +1593,14 @@ class SondeDecoder(object):
|
|||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.error(
|
||||
"Decoder #%s %s %.3f - %s"
|
||||
% (str(self.rtl_device_idx), self.sonde_type, self.sonde_freq / 1e6, line)
|
||||
f"Decoder ({_sdr_name}) {self.sonde_type} {self.sonde_freq/1e6:.3f} - {line}"
|
||||
)
|
||||
|
||||
def log_critical(self, line):
|
||||
|
@ -1541,9 +1608,14 @@ class SondeDecoder(object):
|
|||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.critical(
|
||||
"Decoder #%s %s %.3f - %s"
|
||||
% (str(self.rtl_device_idx), self.sonde_type, self.sonde_freq / 1e6, line)
|
||||
f"Decoder ({_sdr_name}) {self.sonde_type} {self.sonde_freq/1e6:.3f} - {line}"
|
||||
)
|
||||
|
||||
def stop(self, nowait=False):
|
||||
|
|
|
@ -57,7 +57,7 @@ def run_rtl_power(
|
|||
step,
|
||||
filename="log_power.csv",
|
||||
dwell=20,
|
||||
sdr_power="rtl_power",
|
||||
rtl_power_path="rtl_power",
|
||||
device_idx=0,
|
||||
ppm=0,
|
||||
gain=-1,
|
||||
|
@ -71,7 +71,7 @@ def run_rtl_power(
|
|||
step (int): Search step, in Hz.
|
||||
filename (str): Output results to this file. Defaults to ./log_power.csv
|
||||
dwell (int): How long to average on the frequency range for.
|
||||
sdr_power (str): Path to the rtl_power utility.
|
||||
rtl_power_path (str): Path to the rtl_power utility.
|
||||
device_idx (int or str): Device index or serial number of the RTLSDR. Defaults to 0 (the first SDR found).
|
||||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (float): SDR Gain setting, in dB.
|
||||
|
@ -109,7 +109,7 @@ def run_rtl_power(
|
|||
% (
|
||||
timeout_kill,
|
||||
dwell + 10,
|
||||
sdr_power,
|
||||
rtl_power_path,
|
||||
bias_option,
|
||||
start,
|
||||
stop,
|
||||
|
@ -233,8 +233,11 @@ def detect_sonde(
|
|||
frequency,
|
||||
rs_path="./",
|
||||
dwell_time=10,
|
||||
sdr_fm="rtl_fm",
|
||||
device_idx=0,
|
||||
sdr_type="RTLSDR",
|
||||
sdr_hostname="localhost",
|
||||
sdr_port=5555,
|
||||
rtl_fm_path="rtl_fm",
|
||||
rtl_device_idx=0,
|
||||
ppm=0,
|
||||
gain=-1,
|
||||
bias=False,
|
||||
|
@ -247,8 +250,8 @@ def detect_sonde(
|
|||
frequency (int): Frequency to perform the detection on, in Hz.
|
||||
rs_path (str): Path to the RS binaries (i.e rs_detect). Defaults to ./
|
||||
dwell_time (int): Timeout before giving up detection.
|
||||
sdr_fm (str): Path to rtl_fm, or drop-in equivalent. Defaults to 'rtl_fm'
|
||||
device_idx (int or str): Device index or serial number of the RTLSDR. Defaults to 0 (the first SDR found).
|
||||
rtl_fm_path (str): Path to rtl_fm, or drop-in equivalent. Defaults to 'rtl_fm'
|
||||
rtl_device_idx (int or str): Device index or serial number of the RTLSDR. Defaults to 0 (the first SDR found).
|
||||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
|
@ -293,7 +296,7 @@ def detect_sonde(
|
|||
|
||||
# Try and avoid the RTLSDR 403.2 MHz spur.
|
||||
# Note that this is only goign to work if we are detecting on 403.210 or 403.190 MHz.
|
||||
if abs(403200000 - frequency) < 20000:
|
||||
if (abs(403200000 - frequency) < 20000) and (sdr_type == "RTLSDR"):
|
||||
logging.debug("Scanner - Narrowing detection IF BW to avoid RTLSDR spur.")
|
||||
_if_bw = 15
|
||||
|
||||
|
@ -315,20 +318,34 @@ def detect_sonde(
|
|||
|
||||
if _mode == "IQ":
|
||||
# IQ decoding
|
||||
# Sample source (rtl_fm, in IQ mode)
|
||||
rx_test_command = (
|
||||
"timeout %ds %s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |"
|
||||
% (
|
||||
dwell_time * 2,
|
||||
sdr_fm,
|
||||
bias_option,
|
||||
int(ppm),
|
||||
str(device_idx),
|
||||
gain_param,
|
||||
_iq_bw,
|
||||
frequency,
|
||||
)
|
||||
rx_test_command = f"timeout {dwell_time * 2} "
|
||||
|
||||
rx_test_command += get_sdr_iq_cmd(
|
||||
sdr_type=sdr_type,
|
||||
frequency=frequency,
|
||||
sample_rate=_iq_bw,
|
||||
rtl_device_idx = rtl_device_idx,
|
||||
rtl_fm_path = rtl_fm_path,
|
||||
ppm = ppm,
|
||||
gain = gain,
|
||||
bias = bias,
|
||||
sdr_hostname = sdr_hostname,
|
||||
sdr_port = sdr_port
|
||||
)
|
||||
|
||||
# rx_test_command = (
|
||||
# "timeout %ds %s %s-p %d -d %s %s-M raw -F9 -s %d -f %d 2>/dev/null |"
|
||||
# % (
|
||||
# dwell_time * 2,
|
||||
# rtl_fm_path,
|
||||
# bias_option,
|
||||
# int(ppm),
|
||||
# str(device_idx),
|
||||
# gain_param,
|
||||
# _iq_bw,
|
||||
# frequency,
|
||||
# )
|
||||
# )
|
||||
# Saving of Debug audio, if enabled,
|
||||
if save_detection_audio:
|
||||
rx_test_command += "tee detect_%s.raw | " % str(device_idx)
|
||||
|
@ -345,25 +362,44 @@ def detect_sonde(
|
|||
# FM decoding
|
||||
|
||||
# Sample Source (rtl_fm)
|
||||
rx_test_command = (
|
||||
"timeout %ds %s %s-p %d -d %s %s-M fm -F9 -s %d -f %d 2>/dev/null |"
|
||||
% (
|
||||
dwell_time * 2,
|
||||
sdr_fm,
|
||||
bias_option,
|
||||
int(ppm),
|
||||
str(device_idx),
|
||||
gain_param,
|
||||
_rx_bw,
|
||||
frequency,
|
||||
)
|
||||
)
|
||||
# Sample filtering
|
||||
rx_test_command += (
|
||||
"sox -t raw -r %d -e s -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null | "
|
||||
% _rx_bw
|
||||
|
||||
rx_test_command = f"timeout {dwell_time * 2} "
|
||||
|
||||
rx_test_command += get_sdr_fm_cmd(
|
||||
sdr_type=sdr_type,
|
||||
frequency=frequency,
|
||||
filter_bandwidth=_rx_bw,
|
||||
sample_rate=48000,
|
||||
highpass = 20,
|
||||
lowpass = None,
|
||||
rtl_device_idx = rtl_device_idx,
|
||||
rtl_fm_path = rtl_fm_path,
|
||||
ppm = ppm,
|
||||
gain = gain,
|
||||
bias = bias,
|
||||
sdr_hostname = "",
|
||||
sdr_port = 1234,
|
||||
)
|
||||
|
||||
# rx_test_command = (
|
||||
# "timeout %ds %s %s-p %d -d %s %s-M fm -F9 -s %d -f %d 2>/dev/null |"
|
||||
# % (
|
||||
# dwell_time * 2,
|
||||
# rtl_fm_path,
|
||||
# bias_option,
|
||||
# int(ppm),
|
||||
# str(device_idx),
|
||||
# gain_param,
|
||||
# _rx_bw,
|
||||
# frequency,
|
||||
# )
|
||||
# )
|
||||
# # Sample filtering
|
||||
# rx_test_command += (
|
||||
# "sox -t raw -r %d -e s -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null | "
|
||||
# % _rx_bw
|
||||
# )
|
||||
|
||||
# Saving of Debug audio, if enabled,
|
||||
if save_detection_audio:
|
||||
rx_test_command += "tee detect_%s.wav | " % str(device_idx)
|
||||
|
@ -374,12 +410,18 @@ def detect_sonde(
|
|||
os.path.join(rs_path, "dft_detect") + " -t %d 2>/dev/null" % dwell_time
|
||||
)
|
||||
|
||||
_sdr_name = get_sdr_name(
|
||||
sdr_type,
|
||||
rtl_device_idx = rtl_device_idx,
|
||||
sdr_hostname = sdr_hostname,
|
||||
sdr_port = sdr_port
|
||||
)
|
||||
|
||||
logging.debug(
|
||||
"Scanner #%s - Using detection command: %s" % (str(device_idx), rx_test_command)
|
||||
f"Scanner ({_sdr_name}) - Using detection command: {rx_test_command}"
|
||||
)
|
||||
logging.debug(
|
||||
"Scanner #%s - Attempting sonde detection on %.3f MHz"
|
||||
% (str(device_idx), frequency / 1e6)
|
||||
f"Scanner ({_sdr_name})- Attempting sonde detection on {frequency/1e6 :.3f} MHz"
|
||||
)
|
||||
|
||||
try:
|
||||
|
@ -392,23 +434,21 @@ def detect_sonde(
|
|||
# dft_detect returns a code of 1 if no sonde is detected.
|
||||
# logging.debug("Scanner - dfm_detect return code: %s" % e.returncode)
|
||||
if e.returncode == 124:
|
||||
logging.error("Scanner #%s - dft_detect timed out." % str(device_idx))
|
||||
raise IOError("Possible RTLSDR lockup.")
|
||||
logging.error(f"Scanner ({_sdr_name}) - dft_detect timed out.")
|
||||
raise IOError("Possible SDR lockup.")
|
||||
|
||||
elif e.returncode >= 2:
|
||||
ret_output = e.output.decode("utf8")
|
||||
else:
|
||||
_runtime = time.time() - _start
|
||||
logging.debug(
|
||||
"Scanner #%s - dft_detect exited in %.1f seconds with return code %d."
|
||||
% (str(device_idx), _runtime, e.returncode)
|
||||
f"Scanner ({_sdr_name}) - dft_detect exited in {_runtime:.1f} seconds with return code {e.returncode}."
|
||||
)
|
||||
return (None, 0.0)
|
||||
except Exception as e:
|
||||
# Something broke when running the detection function.
|
||||
logging.error(
|
||||
"Scanner #%s - Error when running dft_detect - %s"
|
||||
% (str(device_idx), str(e))
|
||||
f"Scanner ({_sdr_name}) - Error when running dft_detect - {sdr(e)}"
|
||||
)
|
||||
return (None, 0.0)
|
||||
|
||||
|
@ -452,74 +492,74 @@ def detect_sonde(
|
|||
|
||||
if "RS41" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a RS41! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a RS41! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "RS41"
|
||||
elif "RS92" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a RS92! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a RS92! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "RS92"
|
||||
elif "DFM" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a DFM Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a DFM Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "DFM"
|
||||
elif "M10" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a M10 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a M10 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "M10"
|
||||
elif "M20" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a M20 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a M20 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "M20"
|
||||
elif "IMET4" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a iMet-4 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a iMet-4 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "IMET"
|
||||
elif "IMET1" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a iMet Sonde! (Type %s - Unsupported) (Score: %.2f)"
|
||||
% (str(device_idx), _type, _score)
|
||||
"Scanner (%s) - Detected a iMet Sonde! (Type %s - Unsupported) (Score: %.2f)"
|
||||
% (_sdr_name, _type, _score)
|
||||
)
|
||||
_sonde_type = "IMET1"
|
||||
elif "IMETafsk" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a iMet Sonde! (Type %s - Unsupported) (Score: %.2f)"
|
||||
% (str(device_idx), _type, _score)
|
||||
"Scanner (%s) - Detected a iMet Sonde! (Type %s - Unsupported) (Score: %.2f)"
|
||||
% (_sdr_name, _type, _score)
|
||||
)
|
||||
_sonde_type = "IMET1"
|
||||
elif "IMET5" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a iMet-54 Sonde! (Score: %.2f)"
|
||||
% (str(device_idx), _score)
|
||||
"Scanner (%s) - Detected a iMet-54 Sonde! (Score: %.2f)"
|
||||
% (_sdr_name, _score)
|
||||
)
|
||||
_sonde_type = "IMET5"
|
||||
elif "LMS6" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a LMS6 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a LMS6 Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
_sonde_type = "LMS6"
|
||||
elif "C34" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a Meteolabor C34/C50 Sonde! (Not yet supported...) (Score: %.2f)"
|
||||
% (str(device_idx), _score)
|
||||
"Scanner (%s) - Detected a Meteolabor C34/C50 Sonde! (Not yet supported...) (Score: %.2f)"
|
||||
% (_sdr_name, _score)
|
||||
)
|
||||
_sonde_type = "C34C50"
|
||||
elif "MRZ" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a Meteo-Radiy MRZ Sonde! (Score: %.2f)"
|
||||
% (str(device_idx), _score)
|
||||
"Scanner (%s) - Detected a Meteo-Radiy MRZ Sonde! (Score: %.2f)"
|
||||
% (_sdr_name, _score)
|
||||
)
|
||||
if _score < 0:
|
||||
_sonde_type = "-MRZ"
|
||||
|
@ -528,8 +568,8 @@ def detect_sonde(
|
|||
|
||||
elif "MK2LMS" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a 1680 MHz LMS6 Sonde (MK2A Telemetry)! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a 1680 MHz LMS6 Sonde (MK2A Telemetry)! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
if _score < 0:
|
||||
_sonde_type = "-MK2LMS"
|
||||
|
@ -538,8 +578,8 @@ def detect_sonde(
|
|||
|
||||
elif "MEISEI" in _type:
|
||||
logging.debug(
|
||||
"Scanner #%s - Detected a Meisei Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (str(device_idx), _score, _offset_est)
|
||||
"Scanner (%s) - Detected a Meisei Sonde! (Score: %.2f, Offset: %.1f Hz)"
|
||||
% (_sdr_name, _score, _offset_est)
|
||||
)
|
||||
# Not currently sure if we expect to see inverted Meisei sondes.
|
||||
if _score < 0:
|
||||
|
@ -557,7 +597,7 @@ def detect_sonde(
|
|||
#
|
||||
class SondeScanner(object):
|
||||
"""Radiosonde Scanner
|
||||
Continuously scan for radiosondes using a RTLSDR, and pass results onto a callback function
|
||||
Continuously scan for radiosondes using a SDR, and pass results onto a callback function
|
||||
"""
|
||||
|
||||
# Allow up to X consecutive scan errors before giving up.
|
||||
|
@ -582,12 +622,18 @@ class SondeScanner(object):
|
|||
max_peaks=10,
|
||||
scan_check_interval=10,
|
||||
rs_path="./",
|
||||
sdr_power="rtl_power",
|
||||
sdr_fm="rtl_fm",
|
||||
device_idx=0,
|
||||
|
||||
sdr_type="RTLSDR",
|
||||
sdr_hostname="localhost",
|
||||
sdr_port=5555,
|
||||
|
||||
rtl_power_path="rtl_power",
|
||||
rtl_fm_path="rtl_fm",
|
||||
rtl_device_idx=0,
|
||||
gain=-1,
|
||||
ppm=0,
|
||||
bias=False,
|
||||
|
||||
save_detection_audio=False,
|
||||
temporary_block_list={},
|
||||
temporary_block_time=60,
|
||||
|
@ -617,12 +663,26 @@ class SondeScanner(object):
|
|||
max_peaks (int): Maximum number of peaks to search over. Peaks are ordered by signal power before being limited to this number.
|
||||
scan_check_interval (int): If we are using a only_scan list, re-check the RTLSDR works every X scan runs.
|
||||
rs_path (str): Path to the RS binaries (i.e rs_detect). Defaults to ./
|
||||
sdr_power (str): Path to rtl_power, or drop-in equivalent. Defaults to 'rtl_power'
|
||||
sdr_fm (str): Path to rtl_fm, or drop-in equivalent. Defaults to 'rtl_fm'
|
||||
|
||||
sdr_type (str): 'RTLSDR', 'Spyserver' or 'KA9Q'
|
||||
|
||||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
sdr_port (int): Port number of KA9Q Server
|
||||
|
||||
Arguments for RTLSDRs:
|
||||
rtl_power_path (str): Path to rtl_power, or drop-in equivalent. Defaults to 'rtl_power'
|
||||
rtl_fm_path (str): Path to rtl_fm, or drop-in equivalent. Defaults to 'rtl_fm'
|
||||
rtl_device_idx (int or str): Device index or serial number of the RTLSDR. Defaults to 0 (the first SDR found).
|
||||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
|
||||
device_idx (int): SDR Device index. Defaults to 0 (the first SDR found).
|
||||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
|
||||
save_detection_audio (bool): Save the audio used in each detecton to detect_<device_idx>.wav
|
||||
temporary_block_list (dict): A dictionary where each attribute represents a frequency that should be blocked for a set time.
|
||||
temporary_block_time (int): How long (minutes) frequencies in the temporary block list should remain blocked for.
|
||||
|
@ -648,12 +708,19 @@ class SondeScanner(object):
|
|||
self.scan_delay = scan_delay
|
||||
self.max_peaks = max_peaks
|
||||
self.rs_path = rs_path
|
||||
self.sdr_power = sdr_power
|
||||
self.sdr_fm = sdr_fm
|
||||
self.device_idx = device_idx
|
||||
|
||||
self.sdr_type = sdr_type
|
||||
|
||||
self.sdr_hostname = sdr_hostname
|
||||
self.sdr_port = sdr_port
|
||||
|
||||
self.rtl_power_path = rtl_power_path
|
||||
self.rtl_fm_path = rtl_fm_path
|
||||
self.rtl_device_idx = rtl_device_idx
|
||||
self.gain = gain
|
||||
self.ppm = ppm
|
||||
self.bias = bias
|
||||
|
||||
self.callback = callback
|
||||
self.save_detection_audio = save_detection_audio
|
||||
|
||||
|
@ -680,12 +747,15 @@ class SondeScanner(object):
|
|||
# This will become our scanner thread.
|
||||
self.sonde_scan_thread = None
|
||||
|
||||
# Test if the supplied RTLSDR is working.
|
||||
_rtlsdr_ok = rtlsdr_test(device_idx)
|
||||
# Test if the supplied SDR is working.
|
||||
_sdr_ok = test_sdr(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
|
||||
# TODO: How should this error be handled?
|
||||
if not _rtlsdr_ok:
|
||||
self.log_error("RTLSDR #%s non-functional - exiting." % device_idx)
|
||||
if not _sdr_ok:
|
||||
self.sonde_scanner_running = False
|
||||
self.exit_state = "FAILED SDR"
|
||||
return
|
||||
|
@ -737,11 +807,18 @@ class SondeScanner(object):
|
|||
if len(self.only_scan) > 0:
|
||||
self.scan_counter += 1
|
||||
if (self.scan_counter % self.scan_check_interval) == 0:
|
||||
self.log_debug("Performing periodic check of RTLSDR.")
|
||||
_rtlsdr_ok = rtlsdr_test(self.device_idx)
|
||||
if not _rtlsdr_ok:
|
||||
self.log_debug("Performing periodic check of SDR.")
|
||||
|
||||
_sdr_ok = test_sdr(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
|
||||
if not _sdr_ok:
|
||||
self.log_error(
|
||||
"Unrecoverable RTLSDR error. Closing scan thread."
|
||||
"Unrecoverable SDR error. Closing scan thread."
|
||||
)
|
||||
break
|
||||
|
||||
|
@ -749,17 +826,17 @@ class SondeScanner(object):
|
|||
_results = self.sonde_search()
|
||||
|
||||
except (IOError, ValueError) as e:
|
||||
# No log file produced. Reset the RTLSDR and try again.
|
||||
# No log file produced. Reset the SDR and try again.
|
||||
# traceback.print_exc()
|
||||
self.log_warning("RTLSDR produced no output... resetting and retrying.")
|
||||
self.log_warning("SDR produced no output... resetting and retrying.")
|
||||
self.error_retries += 1
|
||||
# Attempt to reset the RTLSDR.
|
||||
if self.device_idx == "0":
|
||||
# If the device ID is 0, we assume we only have a single RTLSDR on this system.
|
||||
reset_all_rtlsdrs()
|
||||
else:
|
||||
# Otherwise, we reset the specific RTLSDR
|
||||
reset_rtlsdr_by_serial(self.device_idx)
|
||||
# Attempt to reset the SDR, if possible.
|
||||
reset_sdr(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
|
||||
time.sleep(10)
|
||||
continue
|
||||
|
@ -802,31 +879,31 @@ class SondeScanner(object):
|
|||
|
||||
if len(self.only_scan) == 0:
|
||||
# No only_scan frequencies provided - perform a scan.
|
||||
run_rtl_power(
|
||||
self.min_freq * 1e6,
|
||||
self.max_freq * 1e6,
|
||||
self.search_step,
|
||||
filename="log_power_%s.csv" % self.device_idx,
|
||||
dwell=self.scan_dwell_time,
|
||||
sdr_power=self.sdr_power,
|
||||
device_idx=self.device_idx,
|
||||
|
||||
(freq, power, step) = get_power_spectrum(
|
||||
sdr_type=self.sdr_type,
|
||||
frequency_start=self.min_freq * 1e6,
|
||||
frequency_stop=self.max_freq * 1e6,
|
||||
step=self.search_step,
|
||||
integration_time=self.scan_dwell_time,
|
||||
rtl_device_idx=self.rtl_device_idx,
|
||||
rtl_power_path=self.rtl_power_path,
|
||||
ppm=self.ppm,
|
||||
gain=self.gain,
|
||||
bias=self.bias,
|
||||
sdr_hostname=self.sdr_hostname,
|
||||
sdr_port=self.sdr_port
|
||||
)
|
||||
|
||||
# Exit opportunity.
|
||||
if self.sonde_scanner_running == False:
|
||||
return []
|
||||
|
||||
# Read in result.
|
||||
# This step will throw an IOError if the file does not exist.
|
||||
(freq, power, step) = read_rtl_power("log_power_%s.csv" % self.device_idx)
|
||||
# Sanity check results.
|
||||
if step == 0 or len(freq) == 0 or len(power) == 0:
|
||||
if step == None or len(freq) == 0 or len(power) == 0:
|
||||
# Otherwise, if a file has been written but contains no data, it can indicate
|
||||
# an issue with the RTLSDR. Sometimes these issues can be resolved by issuing a usb reset to the RTLSDR.
|
||||
raise ValueError("Invalid Log File")
|
||||
raise ValueError("Error getting PSD")
|
||||
|
||||
# Update the global scan result
|
||||
(_freq_decimate, _power_decimate) = peak_decimation(freq / 1e6, power, 10)
|
||||
|
@ -837,7 +914,9 @@ class SondeScanner(object):
|
|||
scan_result["peak_lvl"] = []
|
||||
|
||||
# Rough approximation of the noise floor of the received power spectrum.
|
||||
power_nf = np.mean(power)
|
||||
# Switched to use a Median instead of a Mean 2022-04-02. Should remove outliers better.
|
||||
power_nf = np.median(power)
|
||||
logging.debug(f"Noise Floor Estimate: {power_nf:.1f} dB uncal")
|
||||
# Pass the threshold data to the web client for plotting
|
||||
scan_result["threshold"] = power_nf
|
||||
|
||||
|
@ -976,8 +1055,11 @@ class SondeScanner(object):
|
|||
|
||||
(detected, offset_est) = detect_sonde(
|
||||
_freq,
|
||||
sdr_fm=self.sdr_fm,
|
||||
device_idx=self.device_idx,
|
||||
sdr_type=self.sdr_type,
|
||||
sdr_hostname=self.sdr_hostname,
|
||||
sdr_port=self.sdr_port,
|
||||
rtl_fm_path=self.rtl_fm_path,
|
||||
rtl_device_idx=self.rtl_device_idx,
|
||||
ppm=self.ppm,
|
||||
gain=self.gain,
|
||||
bias=self.bias,
|
||||
|
@ -1062,28 +1144,52 @@ class SondeScanner(object):
|
|||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
logging.debug("Scanner #%s - %s" % (self.device_idx, line))
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.debug(f"Scanner ({_sdr_name}) - {line}")
|
||||
|
||||
def log_info(self, line):
|
||||
"""Helper function to log an informational message with a descriptive heading.
|
||||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
logging.info("Scanner #%s - %s" % (self.device_idx, line))
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.info(f"Scanner ({_sdr_name}) - {line}")
|
||||
|
||||
def log_error(self, line):
|
||||
"""Helper function to log an error message with a descriptive heading.
|
||||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
logging.error("Scanner #%s - %s" % (self.device_idx, line))
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.error(f"Scanner ({_sdr_name}) - {line}")
|
||||
|
||||
def log_warning(self, line):
|
||||
"""Helper function to log a warning message with a descriptive heading.
|
||||
Args:
|
||||
line (str): Message to be logged.
|
||||
"""
|
||||
logging.warning("Scanner #%s - %s" % (self.device_idx, line))
|
||||
_sdr_name = get_sdr_name(
|
||||
self.sdr_type,
|
||||
rtl_device_idx = self.rtl_device_idx,
|
||||
sdr_hostname = self.sdr_hostname,
|
||||
sdr_port = self.sdr_port
|
||||
)
|
||||
logging.warning(f"Scanner ({_sdr_name}) - {line}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,20 +6,25 @@
|
|||
# Released under GNU GPL v3 or later
|
||||
#
|
||||
import logging
|
||||
import os.path
|
||||
import platform
|
||||
import subprocess
|
||||
import numpy as np
|
||||
from io import StringIO
|
||||
|
||||
from .utils import rtlsdr_test
|
||||
from .utils import rtlsdr_test, reset_rtlsdr_by_serial, reset_all_rtlsdrs
|
||||
|
||||
|
||||
def test_sdr(
|
||||
sdr_type: str,
|
||||
rtl_device_idx = "0",
|
||||
sdr_hostname = "",
|
||||
sdr_port = 1234
|
||||
sdr_port = 5555
|
||||
):
|
||||
"""
|
||||
Test the prescence / functionality of a SDR.
|
||||
|
||||
sdr_type (str): 'RTLSDR', 'Spyserver' or 'KA9Q'
|
||||
sdr_type (str): 'RTLSDR', 'SpyServer' or 'KA9Q'
|
||||
|
||||
Arguments for RTLSDRs:
|
||||
rtl_device_id (str) - Device ID for a RTLSDR
|
||||
|
@ -31,6 +36,8 @@ def test_sdr(
|
|||
"""
|
||||
|
||||
if sdr_type == "RTLSDR":
|
||||
# Use the existing rtlsdr_test code, which tries to read some samples
|
||||
# from the specified RTLSDR
|
||||
_ok = rtlsdr_test(rtl_device_idx)
|
||||
if not _ok:
|
||||
logging.error(f"RTLSDR #{rtl_device_idx} non-functional.")
|
||||
|
@ -47,23 +54,102 @@ def test_sdr(
|
|||
|
||||
return _ok
|
||||
|
||||
elif sdr_type == "SpyServer":
|
||||
# Test connectivity to a SpyServer by trying to grab some samples.
|
||||
_cmd = (
|
||||
f"timeout 10 " # Add a timeout, because connections to non-existing IPs seem to block.
|
||||
f"./ss_iq "
|
||||
f"-f 401500000 "
|
||||
f"-s 48000 "
|
||||
f"-r {sdr_hostname} -q {sdr_port} -n 48000 - > /dev/null"
|
||||
)
|
||||
|
||||
logging.debug(f"SpyServer - Testing using command: {_cmd}")
|
||||
|
||||
try:
|
||||
_output = subprocess.check_output(
|
||||
_cmd, shell=True, stderr=subprocess.STDOUT
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Something went wrong...
|
||||
logging.critical(
|
||||
f"SpyServer ({sdr_hostname}:{sdr_port}) - ss_iq call failed with return code {e.returncode}."
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
logging.error(f"Test SDR: Unknown SDR Type {sdr_type}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def reset_sdr(
|
||||
sdr_type: str,
|
||||
rtl_device_idx = "0",
|
||||
sdr_hostname = "",
|
||||
sdr_port = 5555
|
||||
):
|
||||
"""
|
||||
Attempt to reset a SDR. Only used for RTLSDRs.
|
||||
|
||||
sdr_type (str): 'RTLSDR', 'Spyserver' or 'KA9Q'
|
||||
|
||||
Arguments for RTLSDRs:
|
||||
rtl_device_id (str) - Device ID for a RTLSDR
|
||||
|
||||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
sdr_port (int): Port number of KA9Q Server
|
||||
"""
|
||||
|
||||
if sdr_type == "RTLSDR":
|
||||
# Attempt to reset the RTLSDR.
|
||||
if rtl_device_idx == "0":
|
||||
# If the device ID is 0, we assume we only have a single RTLSDR on this system.
|
||||
reset_all_rtlsdrs()
|
||||
else:
|
||||
# Otherwise, we reset the specific RTLSDR
|
||||
reset_rtlsdr_by_serial(rtl_device_idx)
|
||||
|
||||
else:
|
||||
logging.debug(f"No reset ability for SDR type {sdr_type}")
|
||||
|
||||
|
||||
def get_sdr_name(
|
||||
sdr_type: str,
|
||||
rtl_device_idx = "0",
|
||||
sdr_hostname = "",
|
||||
sdr_port = 5555
|
||||
):
|
||||
|
||||
if sdr_type == "RTLSDR":
|
||||
return f"RTLSDR {rtl_device_idx}"
|
||||
|
||||
elif sdr_type == "KA9Q":
|
||||
return f"KA9Q {sdr_hostname}:{sdr_port}"
|
||||
|
||||
elif sdr_type == "SpyServer":
|
||||
return f"SpyServer {sdr_hostname}:{sdr_port}"
|
||||
|
||||
else:
|
||||
return f"UNKNOWN {sdr_type}"
|
||||
|
||||
|
||||
|
||||
def get_sdr_iq_cmd(
|
||||
sdr_type: str,
|
||||
frequency: int,
|
||||
sample_rate: int,
|
||||
rtl_device_idx = "0",
|
||||
rtl_fm_path = "rtl_fm",
|
||||
fast_filter: bool = False,
|
||||
ppm = 0,
|
||||
gain = None,
|
||||
bias = False,
|
||||
sdr_hostname = "",
|
||||
sdr_port = 1234,
|
||||
sdr_port = 5555
|
||||
):
|
||||
"""
|
||||
Get a command-line argument to get IQ (signed 16-bit) from a SDR
|
||||
|
@ -79,6 +165,7 @@ def get_sdr_iq_cmd(
|
|||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
fast_filter (bool): If true, drop the -F9 higher quality filter for rtl_fm
|
||||
|
||||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
|
@ -93,7 +180,8 @@ def get_sdr_iq_cmd(
|
|||
_gain = f"-g {gain:.1f} "
|
||||
|
||||
_cmd = (
|
||||
f"{rtl_fm_path} -M raw -F9 "
|
||||
f"{rtl_fm_path} -M raw "
|
||||
f"{'' if fast_filter else '-F9 '}"
|
||||
f"{'-T ' if bias else ''}"
|
||||
f"-p {int(ppm)} "
|
||||
f"-d {str(rtl_device_idx)} "
|
||||
|
@ -105,8 +193,19 @@ def get_sdr_iq_cmd(
|
|||
|
||||
return _cmd
|
||||
|
||||
if sdr_type == "SpyServer":
|
||||
_cmd = (
|
||||
f"./ss_iq "
|
||||
f"-f {frequency} "
|
||||
f"-s {int(sample_rate)} "
|
||||
f"-r {sdr_hostname} -q {sdr_port} - |"
|
||||
)
|
||||
|
||||
return _cmd
|
||||
|
||||
else:
|
||||
return None
|
||||
logging.critical(f"IQ Source - Unsupported SDR type {sdr_type}")
|
||||
return "false |"
|
||||
|
||||
|
||||
|
||||
|
@ -166,11 +265,11 @@ def get_sdr_fm_cmd(
|
|||
f"{_gain}"
|
||||
f"-s {int(filter_bandwidth)} "
|
||||
f"-f {int(frequency)} "
|
||||
f" 2>/dev/null | "
|
||||
f"2>/dev/null | "
|
||||
)
|
||||
|
||||
# Add in resampling / convertion to wav using sox.
|
||||
_cmd += f"sox -t raw -f {int(filter_bandwidth)} -e s -b 16 -c 1 - -r {int(sample_rate)} -b 16 -t wav - "
|
||||
_cmd += f"sox -t raw -r {int(filter_bandwidth)} -e s -b 16 -c 1 - -r {int(sample_rate)} -b 16 -t wav - "
|
||||
|
||||
if highpass:
|
||||
_cmd += f"highpass {int(highpass)} "
|
||||
|
@ -178,16 +277,204 @@ def get_sdr_fm_cmd(
|
|||
if lowpass:
|
||||
_cmd += f"lowpass {int(lowpass)} "
|
||||
|
||||
_cmd += "- 2> /dev/null | "
|
||||
_cmd += "2> /dev/null | "
|
||||
|
||||
return _cmd
|
||||
|
||||
else:
|
||||
return None
|
||||
logging.critical(f"FM Demod Source - Unsupported SDR type {sdr_type}")
|
||||
return "false |"
|
||||
|
||||
|
||||
def get_power_spectrum(
|
||||
sdr_type: str,
|
||||
frequency_start: int = 400050000,
|
||||
frequency_stop: int = 403000000,
|
||||
step: int = 800,
|
||||
integration_time: int = 20,
|
||||
rtl_device_idx = "0",
|
||||
rtl_power_path = "rtl_power",
|
||||
ppm = 0,
|
||||
gain = None,
|
||||
bias = False,
|
||||
sdr_hostname = "",
|
||||
sdr_port = 5555
|
||||
):
|
||||
"""
|
||||
Get power spectral density data from a SDR.
|
||||
|
||||
Arguments:
|
||||
|
||||
sdr_type (str): 'RTLSDR', 'Spyserver' or 'KA9Q'
|
||||
|
||||
frequency_start (int): Start frequency for the PSD, Hz
|
||||
frequency_stop (int): Stop frequency for the PSD, Hz
|
||||
step (int): Requested frequency step for the PSD, Hz. May not always be honoured.
|
||||
integration_time (int): Integration time in seconds.
|
||||
|
||||
Arguments for RTLSDRs:
|
||||
rtl_device_idx (str) - Device ID for a RTLSDR
|
||||
rtl_power_path (str) - Path to rtl_power. Defaults to just "rtl_power"
|
||||
ppm (int): SDR Frequency accuracy correction, in ppm.
|
||||
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
|
||||
bias (bool): If True, enable the bias tee on the SDR.
|
||||
|
||||
Arguments for KA9Q SDR Server / SpyServer:
|
||||
sdr_hostname (str): Hostname of KA9Q Server
|
||||
sdr_port (int): Port number of KA9Q Server
|
||||
|
||||
|
||||
Returns:
|
||||
(freq, power, step) Tuple
|
||||
|
||||
freq (np.array): Array of frequencies, in Hz
|
||||
power (np.array): Array of uncalibrated power estimates, in Hz
|
||||
step (float): Frequency step of the output data, in Hz.
|
||||
|
||||
Returns (None, None, None) if an error occurs.
|
||||
|
||||
"""
|
||||
|
||||
if sdr_type == "RTLSDR":
|
||||
# Use rtl_power to obtain power spectral density data
|
||||
|
||||
# Create filename to output to.
|
||||
_log_filename = f"log_power_{rtl_device_idx}.csv"
|
||||
|
||||
# If the output log file exists, remove it.
|
||||
if os.path.exists(_log_filename):
|
||||
os.remove(_log_filename)
|
||||
|
||||
|
||||
# Add -k 30 option, to SIGKILL rtl_power 30 seconds after the regular timeout expires.
|
||||
# Note that this only works with the GNU Coreutils version of Timeout, not the IBM version,
|
||||
# which is provided with OSX (Darwin).
|
||||
_platform = platform.system()
|
||||
if "Darwin" in _platform:
|
||||
_timeout_kill = ""
|
||||
else:
|
||||
_timeout_kill = "-k 30 "
|
||||
|
||||
_timeout_cmd = f"timeout {_timeout_kill}{integration_time+10}"
|
||||
|
||||
_gain = ""
|
||||
if gain:
|
||||
if gain >= 0:
|
||||
_gain = f"-g {gain:.1f} "
|
||||
|
||||
_rtl_power_cmd = (
|
||||
f"{_timeout_cmd} {rtl_power_path} "
|
||||
f"{'-T ' if bias else ''}"
|
||||
f"-p {int(ppm)} "
|
||||
#f"-d {str(rtl_device_idx)} "
|
||||
f"{_gain}"
|
||||
f"-f {frequency_start}:{frequency_stop}:{step} "
|
||||
f"-i {integration_time} -1 -c 20% "
|
||||
f"{_log_filename}"
|
||||
)
|
||||
|
||||
_sdr_name = get_sdr_name(
|
||||
sdr_type=sdr_type,
|
||||
rtl_device_idx=rtl_device_idx,
|
||||
sdr_hostname=sdr_hostname,
|
||||
sdr_port=sdr_port
|
||||
)
|
||||
|
||||
logging.info(f"Scanner ({_sdr_name}) - Running frequency scan.")
|
||||
logging.debug(
|
||||
f"Scanner ({_sdr_name}) - Running command: {_rtl_power_cmd}"
|
||||
)
|
||||
|
||||
try:
|
||||
_output = subprocess.check_output(
|
||||
_rtl_power_cmd, shell=True, stderr=subprocess.STDOUT
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
# Something went wrong...
|
||||
logging.critical(
|
||||
f"Scanner ({_sdr_name}) - rtl_power call failed with return code {e.returncode}."
|
||||
)
|
||||
# Look at the error output in a bit more details.
|
||||
_output = e.output.decode("ascii")
|
||||
if "No supported devices found" in _output:
|
||||
logging.critical(
|
||||
f"Scanner ({_sdr_name}) - rtl_power could not find device with ID {rtl_device_idx}, is your configuration correct?"
|
||||
)
|
||||
elif "illegal option" in _output:
|
||||
if bias:
|
||||
logging.critical(
|
||||
f"Scanner ({_sdr_name}) - rtl_power reported an illegal option was used. Are you using a rtl_power version with bias tee support?"
|
||||
)
|
||||
else:
|
||||
logging.critical(
|
||||
f"Scanner ({_sdr_name}) - rtl_power reported an illegal option was used. (This shouldn't happen... are you running an ancient version?)"
|
||||
)
|
||||
else:
|
||||
# Something else odd happened, dump the entire error output to the log for further analysis.
|
||||
logging.critical(
|
||||
f"Scanner ({_sdr_name}) - rtl_power reported error: {_output}"
|
||||
)
|
||||
|
||||
return (None, None, None)
|
||||
|
||||
# OK, now try to read in the saved data.
|
||||
# Output buffers.
|
||||
freq = np.array([])
|
||||
power = np.array([])
|
||||
|
||||
freq_step = 0
|
||||
|
||||
# Open file.
|
||||
f = open(_log_filename, "r")
|
||||
|
||||
# rtl_power log files are csv's, with the first 6 fields in each line describing the time and frequency scan parameters
|
||||
# for the remaining fields, which contain the power samples.
|
||||
|
||||
for line in f:
|
||||
# Split line into fields.
|
||||
fields = line.split(",")
|
||||
|
||||
if len(fields) < 6:
|
||||
logging.error(
|
||||
f"Scanner ({_sdr_name}) - Invalid number of samples in input file - corrupt?"
|
||||
)
|
||||
raise Exception(
|
||||
f"Scanner ({_sdr_name}) - Invalid number of samples in input file - corrupt?"
|
||||
)
|
||||
|
||||
start_date = fields[0]
|
||||
start_time = fields[1]
|
||||
start_freq = float(fields[2])
|
||||
stop_freq = float(fields[3])
|
||||
freq_step = float(fields[4])
|
||||
n_samples = int(fields[5])
|
||||
|
||||
# freq_range = np.arange(start_freq,stop_freq,freq_step)
|
||||
samples = np.loadtxt(StringIO(",".join(fields[6:])), delimiter=",")
|
||||
freq_range = np.linspace(start_freq, stop_freq, len(samples))
|
||||
|
||||
# Add frequency range and samples to output buffers.
|
||||
freq = np.append(freq, freq_range)
|
||||
power = np.append(power, samples)
|
||||
|
||||
f.close()
|
||||
|
||||
# Sanitize power values, to remove the nan's that rtl_power puts in there occasionally.
|
||||
power = np.nan_to_num(power)
|
||||
|
||||
return (freq, power, freq_step)
|
||||
|
||||
else:
|
||||
# Unsupported SDR Type
|
||||
logging.critical(f"Get PSD - Unsupported SDR Type: {sdr_type}")
|
||||
return (None, None, None)
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
logging.basicConfig(
|
||||
format="%(asctime)s %(levelname)s:%(message)s", level=logging.DEBUG
|
||||
)
|
||||
|
||||
_sdr_type = "RTLSDR"
|
||||
|
||||
#print(f"Test RTLSDR 0: {test_sdr(_sdr_type)}")
|
||||
|
@ -202,4 +489,11 @@ if __name__ == "__main__":
|
|||
print(f"RTLSDR IQ (Fixed Gain): {get_sdr_iq_cmd(_sdr_type, _freq, _sample_rate, gain=30.0, bias=True)}")
|
||||
|
||||
print(f"RTLSDR FM (AGC): {get_sdr_fm_cmd(_sdr_type, _freq, _fm_bw, _sample_rate)}")
|
||||
print(f"RTLSDR FM (Fixed Gain): {get_sdr_fm_cmd(_sdr_type, _freq, _fm_bw, _sample_rate, gain=30.0, bias=True, highpass=20)}")
|
||||
print(f"RTLSDR FM (Fixed Gain): {get_sdr_fm_cmd(_sdr_type, _freq, _fm_bw, _sample_rate, gain=30.0, bias=True, highpass=20)}")
|
||||
|
||||
(freq, power, step) = get_power_spectrum(
|
||||
sdr_type="RTLSDR"
|
||||
)
|
||||
print(freq)
|
||||
print(power)
|
||||
print(step)
|
|
@ -37,7 +37,6 @@ REQUIRED_RS_UTILS = [
|
|||
"dft_detect",
|
||||
"dfm09mod",
|
||||
"m10mod",
|
||||
"imet1rs_dft",
|
||||
"rs41mod",
|
||||
"rs92mod",
|
||||
"fsk_demod",
|
||||
|
@ -47,6 +46,7 @@ REQUIRED_RS_UTILS = [
|
|||
"imet54mod",
|
||||
"mp3h1mod",
|
||||
"m20mod",
|
||||
"imet4iq"
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ echo "Building iMet-4 demod."
|
|||
cd ../imet/
|
||||
# Note -O3 flag removed from this demodulator until Bus Error bug can be resolved.
|
||||
gcc imet1rs_dft.c -lm -Ofast -o imet1rs_dft $VERS_FLAG
|
||||
gcc imet4iq.c -lm -Ofast -o imet4iq $VERS_FLAG
|
||||
|
||||
echo "Building fsk-demod utils from codec2"
|
||||
cd ../utils/
|
||||
|
@ -63,23 +64,26 @@ gcc fsk_demod.c fsk.c modem_stats.c kiss_fftr.c kiss_fft.c -lm -O3 -o fsk_demod
|
|||
#gcc tsrc.c -o tsrc -lm -lsamplerate
|
||||
# If running under OSX and using MacPorts, you may need to uncomment the following line to be able to find libsamplerate.
|
||||
#gcc tsrc.c -o tsrc -lm -lsamplerate -I/opt/local/include -L/opt/local/lib
|
||||
# ... and for homebrew users.
|
||||
#gcc tsrc.c -o tsrc -lm -lsamplerate -I/opt/homebrew/include -L/opt/homebrew/lib
|
||||
|
||||
|
||||
# Copy all necessary files into this directory.
|
||||
echo "Copying files into auto_rx directory."
|
||||
cd ../auto_rx/
|
||||
cp ../scan/dft_detect .
|
||||
cp ../utils/fsk_demod .
|
||||
cp ../imet/imet1rs_dft .
|
||||
cp ../mk2a/mk2mod .
|
||||
cp ../demod/mod/rs41mod .
|
||||
cp ../demod/mod/dfm09mod .
|
||||
cp ../demod/mod/m10mod .
|
||||
cp ../demod/mod/m20mod .
|
||||
cp ../demod/mod/rs92mod .
|
||||
cp ../demod/mod/lms6Xmod .
|
||||
cp ../demod/mod/meisei100mod .
|
||||
cp ../demod/mod/imet54mod .
|
||||
cp ../demod/mod/mp3h1mod .
|
||||
mv ../scan/dft_detect .
|
||||
mv ../utils/fsk_demod .
|
||||
mv ../imet/imet1rs_dft .
|
||||
mv ../imet/imet4iq .
|
||||
mv ../mk2a/mk2mod .
|
||||
mv ../demod/mod/rs41mod .
|
||||
mv ../demod/mod/dfm09mod .
|
||||
mv ../demod/mod/m10mod .
|
||||
mv ../demod/mod/m20mod .
|
||||
mv ../demod/mod/rs92mod .
|
||||
mv ../demod/mod/lms6Xmod .
|
||||
mv ../demod/mod/meisei100mod .
|
||||
mv ../demod/mod/imet54mod .
|
||||
mv ../demod/mod/mp3h1mod .
|
||||
|
||||
echo "Done!"
|
||||
|
|
|
@ -9,20 +9,54 @@
|
|||
# - [search_params] -> min_freq, max_freq - Set these suitable for your location!
|
||||
#
|
||||
|
||||
###################
|
||||
# RTLSDR SETTINGS #
|
||||
###################
|
||||
################
|
||||
# SDR SETTINGS #
|
||||
################
|
||||
[sdr]
|
||||
|
||||
# Number of RTLSDRs to use.
|
||||
#
|
||||
# SDR Type
|
||||
#
|
||||
# RTLSDR - Use one or more RTLSDRs
|
||||
#
|
||||
# EXPERIMENTAL / NOT IMPLEMENTED options:
|
||||
# KA9Q - Use a KA9Q SDR Server
|
||||
# SpyServer - Use a SpyServer
|
||||
#
|
||||
sdr_type = RTLSDR
|
||||
|
||||
#
|
||||
# Number of SDRs or SDR Connection Threads to use
|
||||
#
|
||||
# If SDR type is either KA9Q or SpyServer, this defines the maximum number of parallel
|
||||
# decoding/scan tasks.
|
||||
# If SDR type is set to RTLSDR above, then this number is the number of individual RTLSDRs
|
||||
# that will be used, eith each RTLSDR allocated a scan or decode task.
|
||||
# If more than one RTLSDR is in use, multiple [sdr_X] sections must be populated below
|
||||
#
|
||||
sdr_quantity = 1
|
||||
|
||||
# Individual SDR Settings.
|
||||
|
||||
#
|
||||
# Network SDR Connection Details
|
||||
#
|
||||
# If using either a KA9Q or SpyServer network server, the hostname and port
|
||||
# of the server needs to be defined below. Usually this will be running on the
|
||||
# same machine as auto_rx, so the defaults are usually fine.
|
||||
#
|
||||
sdr_hostname = localhost
|
||||
sdr_port = 5555
|
||||
|
||||
#
|
||||
# Individual RTLSDR Settings
|
||||
#
|
||||
# Provide details of your RTLSDRs here, e.g. device numbers, gain settings, and PPM offsets.
|
||||
#
|
||||
[sdr_1]
|
||||
# Device Index / Serial
|
||||
# If using a single RTLSDR, set this value to 0
|
||||
# If using multiple SDRs, you MUST allocate each SDR a unique serial number using rtl_eeprom
|
||||
# The serial number must NOT be 00000000 or 00000001, as this causes big confusion to the rtl utilities.
|
||||
# i.e. to set the serial number of a (single) connected RTLSDR: rtl_eeprom -s 00000002
|
||||
# Then set the device_idx below to 00000002, and repeat for the other [sdr_n] sections below
|
||||
#
|
||||
|
@ -68,6 +102,9 @@ bias = False
|
|||
# In these areas I suggest using the only_scan feature below instead of using the peak-detect search.
|
||||
# You may also need to apply a small offset to the frequency for decoding reliability (i.e. 1676.025 MHz) as
|
||||
# the sondes are often off-frequency. For now, check in something like GQRX to get an idea of what offset is required.
|
||||
#
|
||||
# Note - when using either a KA9Q or SpyServer as the SDR backend, the frequency scan limits are set by the
|
||||
# Server.
|
||||
|
||||
min_freq = 400.05
|
||||
max_freq = 403.0
|
||||
|
|
|
@ -29,15 +29,28 @@ CSV_DIR = "./results/"
|
|||
# }
|
||||
|
||||
|
||||
# soft-decision decoding, with a +0.25 Fs signal centre.
|
||||
# sonde_types = {
|
||||
# 'RS41': {'csv':'rs41_fsk_demod_soft.txt', 'packets': 118, 'color': 'C0'},
|
||||
# 'RS92': {'csv':'rs92_fsk_demod_soft.txt', 'packets': 120, 'color': 'C1'},
|
||||
# 'RS92-NGP': {'csv':'rs92ngp_fsk_demod_soft.txt', 'packets': 120, 'color': 'C2'},
|
||||
# 'DFM09': {'csv':'dfm_fsk_demod_soft.txt', 'packets': 96, 'color': 'C3'},
|
||||
# 'M10': {'csv':'m10_fsk_demod_soft.txt', 'packets': 120, 'color': 'C4'},
|
||||
# 'LMS6-400': {'csv':'lms6-400_fsk_demod_soft.txt', 'packets': 120, 'color': 'C5'},
|
||||
# 'MRZ': {'csv':'mrz_fsk_demod_soft.txt', 'packets': 105, 'color': 'C6'},
|
||||
# 'iMet-54': {'csv':'imet54_fsk_demod_soft.txt', 'packets': 240, 'color': 'C7'},
|
||||
# }
|
||||
|
||||
# soft-decision decoding, with a 0Hz signal centre.
|
||||
sonde_types = {
|
||||
'RS41': {'csv':'rs41_fsk_demod_soft.txt', 'packets': 118, 'color': 'C0'},
|
||||
'RS92': {'csv':'rs92_fsk_demod_soft.txt', 'packets': 120, 'color': 'C1'},
|
||||
'RS92-NGP': {'csv':'rs92ngp_fsk_demod_soft.txt', 'packets': 120, 'color': 'C2'},
|
||||
'DFM09': {'csv':'dfm_fsk_demod_soft.txt', 'packets': 96, 'color': 'C3'},
|
||||
'M10': {'csv':'m10_fsk_demod_soft.txt', 'packets': 120, 'color': 'C4'},
|
||||
'LMS6-400': {'csv':'lms6-400_fsk_demod_soft.txt', 'packets': 120, 'color': 'C5'},
|
||||
'MRZ': {'csv':'mrz_fsk_demod_soft.txt', 'packets': 105, 'color': 'C6'},
|
||||
'iMet-54': {'csv':'imet54_fsk_demod_soft.txt', 'packets': 240, 'color': 'C7'},
|
||||
'RS41': {'csv':'rs41_fsk_demod_soft_centre.txt', 'packets': 118, 'color': 'C0'},
|
||||
'RS92': {'csv':'rs92_fsk_demod_soft_centre.txt', 'packets': 120, 'color': 'C1'},
|
||||
'RS92-NGP': {'csv':'rs92ngp_fsk_demod_soft_centre.txt', 'packets': 120, 'color': 'C2'},
|
||||
'DFM09': {'csv':'dfm_fsk_demod_soft_centre.txt', 'packets': 96, 'color': 'C3'},
|
||||
'M10': {'csv':'m10_fsk_demod_soft_centre.txt', 'packets': 120, 'color': 'C4'},
|
||||
'LMS6-400': {'csv':'lms6-400_fsk_demod_soft_centre.txt', 'packets': 120, 'color': 'C5'},
|
||||
'MRZ': {'csv':'mrz_fsk_demod_soft_centre.txt', 'packets': 105, 'color': 'C6'},
|
||||
'iMet-54': {'csv':'imet54_fsk_demod_soft_centre.txt', 'packets': 240, 'color': 'C7'},
|
||||
}
|
||||
|
||||
|
||||
|
@ -85,5 +98,5 @@ plt.legend()
|
|||
plt.grid()
|
||||
plt.ylabel("Packet Error Rate")
|
||||
plt.xlabel("Eb/No (dB)")
|
||||
plt.title("auto_rx Decode Chain Performance - fsk_demod")
|
||||
plt.title("auto_rx Decode Chain Performance - fsk_demod soft-decision 0 Hz")
|
||||
plt.show()
|
|
@ -207,6 +207,16 @@ processing_type = {
|
|||
"post_process" : " | grep frame | wc -l",
|
||||
'files' : "./generated/rs41*"
|
||||
},
|
||||
'rs41_fsk_demod_soft_centre': {
|
||||
# Keep signal centred.
|
||||
'demod' : "| csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs41mod --ecc --ptu --crc --softin -i --json 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep frame | wc -l",
|
||||
'files' : "./generated/rs41*"
|
||||
},
|
||||
# RS92 Decoding
|
||||
'rs92_fsk_demod_soft': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
|
@ -218,6 +228,16 @@ processing_type = {
|
|||
"post_process" : " | grep M2513116 | wc -l",
|
||||
'files' : "./generated/rs92*"
|
||||
},
|
||||
'rs92_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs92mod -vx -v --crc --ecc --vel --softin -i 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep M2513116 | wc -l",
|
||||
'files' : "./generated/rs92*"
|
||||
},
|
||||
# RS92-NGP Decoding
|
||||
'rs92ngp_fsk_demod_soft': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
|
@ -229,6 +249,16 @@ processing_type = {
|
|||
"post_process" : " | grep P3213708 | wc -l",
|
||||
'files' : "./generated/rsngp*"
|
||||
},
|
||||
'rs92ngp_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../fsk_demod --cs16 -b -20000 -u 20000 -s --stats=5 2 96000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs92mod -vx -v --crc --ecc --vel --ngp --softin -i 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep P3213708 | wc -l",
|
||||
'files' : "./generated/rsngp*"
|
||||
},
|
||||
'm10_fsk_demod_soft': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr shift_addition_cc 0.125 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.50083333333 -c | ../fsk_demod --cs16 -b 1 -p 5 -u 23000 -s --stats=5 2 48080 9616 - - 2>stats.txt |",
|
||||
|
@ -237,6 +267,14 @@ processing_type = {
|
|||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
'm10_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 0.50083333333 -c | ../fsk_demod --cs16 -b -10000 -p 5 -u 10000 -s --stats=5 2 48080 9616 - - 2>stats.txt |",
|
||||
'decode': "../m10mod --json --softin -i -vvv 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep aprsid | wc -l",
|
||||
'files' : "./generated/m10*"
|
||||
},
|
||||
'dfm_fsk_demod_soft': {
|
||||
# cat ./generated/dfm09_96k_float_15.0dB.bin | csdr shift_addition_cc 0.25000 2>/dev/null | csdr convert_f_s16 |
|
||||
#./tsrc - - 1.041666 | ../fsk_demod --cs16 -b 1 -u 45000 2 100000 2500 - - 2>/dev/null |
|
||||
|
@ -249,7 +287,18 @@ processing_type = {
|
|||
#"post_process" : "| grep -o '\[OK\]' | wc -l", # No ECC
|
||||
'files' : "./generated/dfm*.bin"
|
||||
},
|
||||
'dfm_fsk_demod_soft_centre': {
|
||||
# cat ./generated/dfm09_96k_float_15.0dB.bin | csdr shift_addition_cc 0.25000 2>/dev/null | csdr convert_f_s16 |
|
||||
#./tsrc - - 1.041666 | ../fsk_demod --cs16 -b 1 -u 45000 2 100000 2500 - - 2>/dev/null |
|
||||
#python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null|
|
||||
#../dfm09ecc -vv --json --dist --auto
|
||||
|
||||
'demod': '| csdr convert_f_s16 | ../tsrc - - 0.5208| ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 50000 2500 - - 2>stats.txt |',#' python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null| ',
|
||||
'decode': '../dfm09mod -vv --json --dist --auto --softin -i 2>/dev/null',
|
||||
"post_process" : " | grep frame | wc -l", # ECC
|
||||
#"post_process" : "| grep -o '\[OK\]' | wc -l", # No ECC
|
||||
'files' : "./generated/dfm*.bin"
|
||||
},
|
||||
# LMS6-400 Decoding
|
||||
'lms6-400_fsk_demod_soft': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
|
@ -261,7 +310,16 @@ processing_type = {
|
|||
"post_process" : "| grep frame | wc -l",
|
||||
'files' : "./generated/lms6-400*",
|
||||
},
|
||||
'lms6-400_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../lms6Xmod --json --softin -i 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep frame | wc -l",
|
||||
'files' : "./generated/lms6-400*",
|
||||
},
|
||||
# iMet-54 Decoding
|
||||
'imet54_fsk_demod_soft': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
|
@ -273,7 +331,16 @@ processing_type = {
|
|||
"post_process" : "| grep frame | wc -l",
|
||||
'files' : "./generated/imet54*",
|
||||
},
|
||||
'imet54_fsk_demod_soft_centre': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr convert_f_s16 | ../tsrc - - 0.500 | ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../imet54mod --ecc --json --softin -i 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| grep frame | wc -l",
|
||||
'files' : "./generated/imet54*",
|
||||
},
|
||||
# MRZ Sonde decoding - Soft Input
|
||||
'mrz_fsk_demod_soft': {
|
||||
'demod': '| csdr shift_addition_cc 0.125000 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.50| ../fsk_demod --cs16 -s -b 1250 -u 23750 --stats=5 2 48000 2400 - - 2>stats.txt |',
|
||||
|
@ -281,6 +348,19 @@ processing_type = {
|
|||
"post_process" : " | grep -F [OK] | wc -l", # ECC
|
||||
'files' : "./generated/mrz*.bin"
|
||||
},
|
||||
'mrz_fsk_demod_soft_centre': {
|
||||
'demod': '| csdr convert_f_s16 | ../tsrc - - 0.500 | ../fsk_demod --cs16 -s -b -10000 -u 10000 --stats=5 2 48000 2400 - - 2>stats.txt |',
|
||||
'decode': '../mp3h1mod -vv --softin --json --auto 2>/dev/null',
|
||||
"post_process" : " | grep -F [OK] | wc -l", # ECC
|
||||
'files' : "./generated/mrz*.bin"
|
||||
},
|
||||
'imet4_iq': {
|
||||
'demod': '| csdr convert_f_s16 | ../tsrc - - 0.50|',
|
||||
'decode': '../imet4iq --iq 0.0 --lpIQ --dc - 48000 16 --json 2> /dev/null',
|
||||
"post_process" : "| grep -F [OK] | wc -l", # ECC
|
||||
'files' : "./generated/imet4*.bin"
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -726,7 +806,7 @@ def run_analysis(mode, file_mask=None, shift=0.0, verbose=False, log_output = No
|
|||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-m", "--mode", type=str, default="rs41_fsk_demod", help="Operation mode.")
|
||||
parser.add_argument("-m", "--mode", type=str, default="rs41_fsk_demod_soft", help="Operation mode.")
|
||||
parser.add_argument("-f", "--files", type=str, default=None, help="Glob-path to files to run over.")
|
||||
parser.add_argument("-v", "--verbose", action='store_true', default=False, help="Show additional debug info.")
|
||||
parser.add_argument("-d", "--dry-run", action='store_true', default=False, help="Show additional debug info.")
|
||||
|
@ -743,7 +823,8 @@ if __name__ == "__main__":
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
batch_modes = ['dfm_fsk_demod_soft', 'rs41_fsk_demod_soft', 'm10_fsk_demod_soft', 'rs92_fsk_demod_soft', 'rs92ngp_fsk_demod_soft', 'lms6-400_fsk_demod_soft', 'imet4_rtlfm', 'mrz_fsk_demod_soft', 'imet54_fsk_demod_soft']
|
||||
#batch_modes = ['dfm_fsk_demod_soft', 'rs41_fsk_demod_soft', 'm10_fsk_demod_soft', 'rs92_fsk_demod_soft', 'rs92ngp_fsk_demod_soft', 'lms6-400_fsk_demod_soft', 'imet4_rtlfm', 'mrz_fsk_demod_soft', 'imet54_fsk_demod_soft']
|
||||
batch_modes = ['dfm_fsk_demod_soft_centre', 'rs41_fsk_demod_soft_centre', 'm10_fsk_demod_soft_centre', 'rs92_fsk_demod_soft_centre', 'rs92ngp_fsk_demod_soft_centre', 'lms6-400_fsk_demod_soft_centre', 'imet4_iq', 'mrz_fsk_demod_soft_centre', 'imet54_fsk_demod_soft_centre']
|
||||
|
||||
if args.batch:
|
||||
for _mode in batch_modes:
|
||||
|
|
Plik diff jest za duży
Load Diff
Ładowanie…
Reference in New Issue