add airspy source; fix offset tuning
This commit is contained in:
parent
5375580104
commit
de51e266f6
@ -106,7 +106,7 @@ sdrs = {
|
|||||||
"type": "rtl_sdr",
|
"type": "rtl_sdr",
|
||||||
"ppm": 0,
|
"ppm": 0,
|
||||||
# you can change this if you use an upconverter. formula is:
|
# you can change this if you use an upconverter. formula is:
|
||||||
# shown_center_freq = center_freq + lfo_offset
|
# center_freq + lfo_offset = actual frequency on the sdr
|
||||||
# "lfo_offset": 0,
|
# "lfo_offset": 0,
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"70cm": {
|
"70cm": {
|
||||||
|
@ -1046,7 +1046,7 @@ function on_ws_recv(evt) {
|
|||||||
starting_mod = config['start_mod'];
|
starting_mod = config['start_mod'];
|
||||||
starting_offset_frequency = config['start_offset_freq'];
|
starting_offset_frequency = config['start_offset_freq'];
|
||||||
bandwidth = config['samp_rate'];
|
bandwidth = config['samp_rate'];
|
||||||
center_freq = config['center_freq'] + config['lfo_offset'];
|
center_freq = config['center_freq'];
|
||||||
fft_size = config['fft_size'];
|
fft_size = config['fft_size'];
|
||||||
fft_fps = config['fft_fps'];
|
fft_fps = config['fft_fps'];
|
||||||
var audio_compression = config['audio_compression'];
|
var audio_compression = config['audio_compression'];
|
||||||
|
@ -57,7 +57,6 @@ class OpenWebRxReceiverClient(Client):
|
|||||||
"waterfall_min_level",
|
"waterfall_min_level",
|
||||||
"waterfall_max_level",
|
"waterfall_max_level",
|
||||||
"waterfall_auto_level_margin",
|
"waterfall_auto_level_margin",
|
||||||
"lfo_offset",
|
|
||||||
"samp_rate",
|
"samp_rate",
|
||||||
"fft_size",
|
"fft_size",
|
||||||
"fft_fps",
|
"fft_fps",
|
||||||
|
@ -20,11 +20,12 @@ class FeatureDetector(object):
|
|||||||
features = {
|
features = {
|
||||||
"core": ["csdr", "nmux", "nc"],
|
"core": ["csdr", "nmux", "nc"],
|
||||||
"rtl_sdr": ["rtl_sdr"],
|
"rtl_sdr": ["rtl_sdr"],
|
||||||
"rtl_sdr_connector": ["owrx_connector"],
|
"rtl_sdr_connector": ["rtl_connector"],
|
||||||
"sdrplay": ["rx_tools"],
|
"sdrplay": ["rx_tools"],
|
||||||
"sdrplay_connector": ["owrx_connector"],
|
"sdrplay_connector": ["soapy_connector"],
|
||||||
"hackrf": ["hackrf_transfer"],
|
"hackrf": ["hackrf_transfer"],
|
||||||
"airspy": ["airspy_rx"],
|
"airspy": ["airspy_rx"],
|
||||||
|
"airspy_connector": ["soapy_connector"],
|
||||||
"digital_voice_digiham": ["digiham", "sox"],
|
"digital_voice_digiham": ["digiham", "sox"],
|
||||||
"digital_voice_dsd": ["dsd", "sox", "digiham"],
|
"digital_voice_dsd": ["dsd", "sox", "digiham"],
|
||||||
"wsjt-x": ["wsjtx", "sox"],
|
"wsjt-x": ["wsjtx", "sox"],
|
||||||
@ -194,39 +195,39 @@ class FeatureDetector(object):
|
|||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def has_owrx_connector(self):
|
def _check_connector(self, command):
|
||||||
|
required_version = LooseVersion("0.1")
|
||||||
|
|
||||||
|
owrx_connector_version_regex = re.compile("^owrx-connector version (.*)$")
|
||||||
|
|
||||||
|
try:
|
||||||
|
process = subprocess.Popen([command, "--version"], stdout=subprocess.PIPE)
|
||||||
|
matches = owrx_connector_version_regex.match(process.stdout.readline().decode())
|
||||||
|
if matches is None:
|
||||||
|
return False
|
||||||
|
version = LooseVersion(matches.group(1))
|
||||||
|
process.wait(1)
|
||||||
|
return version >= required_version
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def has_rtl_connector(self):
|
||||||
"""
|
"""
|
||||||
The owrx_connector package offers direct interfacing between your hardware and openwebrx. It allows quicker
|
The owrx_connector package offers direct interfacing between your hardware and openwebrx. It allows quicker
|
||||||
frequency switching, uses less CPU and can even provide more stability in some cases.
|
frequency switching, uses less CPU and can even provide more stability in some cases.
|
||||||
|
|
||||||
You can get it here: https://github.com/jketterl/owrx_connector
|
You can get it here: https://github.com/jketterl/owrx_connector
|
||||||
"""
|
"""
|
||||||
required_version = LooseVersion("0.1")
|
return self._check_connector("rtl_connector")
|
||||||
|
|
||||||
owrx_connector_version_regex = re.compile("^owrx-connector version (.*)$")
|
def has_soapy_connector(self):
|
||||||
|
"""
|
||||||
|
The owrx_connector package offers direct interfacing between your hardware and openwebrx. It allows quicker
|
||||||
|
frequency switching, uses less CPU and can even provide more stability in some cases.
|
||||||
|
|
||||||
def check_owrx_connector_version(command):
|
You can get it here: https://github.com/jketterl/owrx_connector
|
||||||
try:
|
"""
|
||||||
process = subprocess.Popen([command, "--version"], stdout=subprocess.PIPE)
|
return self._check_connector("soapy_connector")
|
||||||
matches = owrx_connector_version_regex.match(process.stdout.readline().decode())
|
|
||||||
if matches is None:
|
|
||||||
return False
|
|
||||||
version = LooseVersion(matches.group(1))
|
|
||||||
process.wait(1)
|
|
||||||
return version >= required_version
|
|
||||||
except FileNotFoundError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
return reduce(
|
|
||||||
and_,
|
|
||||||
map(
|
|
||||||
check_owrx_connector_version,
|
|
||||||
[
|
|
||||||
"rtl_connector",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def has_dsd(self):
|
def has_dsd(self):
|
||||||
"""
|
"""
|
||||||
|
@ -136,7 +136,7 @@ class SdrSource(object):
|
|||||||
self.busyState = SdrSource.BUSYSTATE_IDLE
|
self.busyState = SdrSource.BUSYSTATE_IDLE
|
||||||
|
|
||||||
def getEventNames(self):
|
def getEventNames(self):
|
||||||
return ["samp_rate", "nmux_memory", "center_freq", "ppm", "rf_gain", "lna_gain", "rf_amp", "antenna", "if_gain"]
|
return ["samp_rate", "nmux_memory", "center_freq", "ppm", "rf_gain", "lna_gain", "rf_amp", "antenna", "if_gain", "lfo_offset"]
|
||||||
|
|
||||||
def wireEvents(self):
|
def wireEvents(self):
|
||||||
def restart(name, value):
|
def restart(name, value):
|
||||||
@ -190,6 +190,14 @@ class SdrSource(object):
|
|||||||
def useNmux(self):
|
def useNmux(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def getCommandValues(self):
|
||||||
|
dict = self.rtlProps.collect(*self.getEventNames()).__dict__()
|
||||||
|
if "lfo_offset" in dict:
|
||||||
|
dict["tuner_freq"] = dict["center_freq"] + dict["lfo_offset"]
|
||||||
|
else:
|
||||||
|
dict["tuner_freq"] = dict["center_freq"]
|
||||||
|
return dict
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.modificationLock.acquire()
|
self.modificationLock.acquire()
|
||||||
if self.monitor:
|
if self.monitor:
|
||||||
@ -199,7 +207,7 @@ class SdrSource(object):
|
|||||||
props = self.rtlProps
|
props = self.rtlProps
|
||||||
|
|
||||||
cmd = self.getCommand().format(
|
cmd = self.getCommand().format(
|
||||||
**props.collect(*self.getEventNames()).__dict__()
|
**self.getCommandValues()
|
||||||
)
|
)
|
||||||
|
|
||||||
format_conversion = self.getFormatConversion()
|
format_conversion = self.getFormatConversion()
|
||||||
@ -447,8 +455,11 @@ class ConnectorSource(SdrSource):
|
|||||||
def reconfigure(prop, value):
|
def reconfigure(prop, value):
|
||||||
if self.monitor is None:
|
if self.monitor is None:
|
||||||
return
|
return
|
||||||
logger.debug("sending property change over control socket: {0} changed to {1}".format(prop, value))
|
v = value
|
||||||
self.controlSocket.sendall("{prop}:{value}\n".format(prop=prop, value=value).encode())
|
if prop == "center_freq" and "lfo_offset" in self.rtlProps:
|
||||||
|
v = value + self.rtlProps["lfo_offset"]
|
||||||
|
logger.debug("sending property change over control socket: {0} changed to {1}".format(prop, v))
|
||||||
|
self.controlSocket.sendall("{prop}:{value}\n".format(prop=prop, value=v).encode())
|
||||||
|
|
||||||
self.rtlProps.wire(reconfigure)
|
self.rtlProps.wire(reconfigure)
|
||||||
|
|
||||||
@ -472,27 +483,45 @@ class ConnectorSource(SdrSource):
|
|||||||
|
|
||||||
class RtlSdrConnectorSource(ConnectorSource):
|
class RtlSdrConnectorSource(ConnectorSource):
|
||||||
def getEventNames(self):
|
def getEventNames(self):
|
||||||
return ["samp_rate", "center_freq", "ppm", "rf_gain", "device"]
|
return ["samp_rate", "center_freq", "ppm", "rf_gain", "device", "iqswap", "lfo_offset"]
|
||||||
|
|
||||||
def getCommand(self):
|
def getCommand(self):
|
||||||
return "rtl_connector -p {port} -c {controlPort}".format(port=self.port, controlPort=self.controlPort) + " -s {samp_rate} -f {center_freq} -g {rf_gain} -P {ppm} -d {device}"
|
cmd = "rtl_connector -p {port} -c {controlPort}".format(port=self.port, controlPort=self.controlPort) +\
|
||||||
|
" -s {samp_rate} -f {tuner_freq} -g {rf_gain} -P {ppm} -d {device}"
|
||||||
|
|
||||||
class SdrplayConnectorSource(ConnectorSource):
|
|
||||||
def getEventNames(self):
|
|
||||||
return ["samp_rate", "center_freq", "ppm", "rf_gain", "antenna", "device", "iqswap"]
|
|
||||||
|
|
||||||
def getCommand(self):
|
|
||||||
cmd = "soapy_connector -p {port} -c {controlPort}".format(port=self.port, controlPort=self.controlPort) +\
|
|
||||||
" -s {samp_rate} -f {center_freq} -g \"{rf_gain}\" -P {ppm} -a \"{antenna}\" -d \"{device}\""
|
|
||||||
if self.rtlProps["iqswap"]:
|
if self.rtlProps["iqswap"]:
|
||||||
cmd += " -i"
|
cmd += " -i"
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
class SdrplayConnectorSource(ConnectorSource):
|
||||||
|
def getEventNames(self):
|
||||||
|
return ["samp_rate", "center_freq", "ppm", "rf_gain", "antenna", "device", "iqswap", "lfo_offset"]
|
||||||
|
|
||||||
|
def getCommand(self):
|
||||||
|
cmd = "soapy_connector -p {port} -c {controlPort}".format(port=self.port, controlPort=self.controlPort) +\
|
||||||
|
" -s {samp_rate} -f {tuner_freq} -g \"{rf_gain}\" -P {ppm} -a \"{antenna}\" -d \"{device}\""
|
||||||
|
if self.rtlProps["iqswap"]:
|
||||||
|
cmd += " -i"
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
class AirspyConnectorSource(ConnectorSource):
|
||||||
|
def getEventNames(self):
|
||||||
|
return ["samp_rate", "center_freq", "ppm", "rf_gain", "device", "iqswap", "lfo_offset", "bias_tee"]
|
||||||
|
|
||||||
|
def getCommand(self):
|
||||||
|
cmd = "soapy_connector -p {port} -c {controlPort}".format(port=self.port, controlPort=self.controlPort) + \
|
||||||
|
" -s {samp_rate} -f {tuner_freq} -g \"{rf_gain}\" -P {ppm} -d \"{device}\""
|
||||||
|
if self.rtlProps["iqswap"]:
|
||||||
|
cmd += " -i"
|
||||||
|
if self.rtlProps["bias_tee"]:
|
||||||
|
cmd += " -t biastee=true"
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
class RtlSdrSource(SdrSource):
|
class RtlSdrSource(SdrSource):
|
||||||
def getCommand(self):
|
def getCommand(self):
|
||||||
return "rtl_sdr -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -"
|
return "rtl_sdr -s {samp_rate} -f {tuner_freq} -p {ppm} -g {rf_gain} -"
|
||||||
|
|
||||||
def getFormatConversion(self):
|
def getFormatConversion(self):
|
||||||
return "csdr convert_u8_f"
|
return "csdr convert_u8_f"
|
||||||
@ -500,7 +529,7 @@ class RtlSdrSource(SdrSource):
|
|||||||
|
|
||||||
class HackrfSource(SdrSource):
|
class HackrfSource(SdrSource):
|
||||||
def getCommand(self):
|
def getCommand(self):
|
||||||
return "hackrf_transfer -s {samp_rate} -f {center_freq} -g {rf_gain} -l{lna_gain} -a{rf_amp} -r-"
|
return "hackrf_transfer -s {samp_rate} -f {tuner_freq} -g {rf_gain} -l{lna_gain} -a{rf_amp} -r-"
|
||||||
|
|
||||||
def getFormatConversion(self):
|
def getFormatConversion(self):
|
||||||
return "csdr convert_s8_f"
|
return "csdr convert_s8_f"
|
||||||
@ -508,7 +537,7 @@ class HackrfSource(SdrSource):
|
|||||||
|
|
||||||
class SdrplaySource(SdrSource):
|
class SdrplaySource(SdrSource):
|
||||||
def getCommand(self):
|
def getCommand(self):
|
||||||
command = "rx_sdr -F CF32 -s {samp_rate} -f {center_freq} -p {ppm}"
|
command = "rx_sdr -F CF32 -s {samp_rate} -f {tuner_freq} -p {ppm}"
|
||||||
gainMap = {"rf_gain": "RFGR", "if_gain": "IFGR"}
|
gainMap = {"rf_gain": "RFGR", "if_gain": "IFGR"}
|
||||||
gains = [
|
gains = [
|
||||||
"{0}={{{1}}}".format(gainMap[name], name)
|
"{0}={{{1}}}".format(gainMap[name], name)
|
||||||
@ -528,7 +557,7 @@ class SdrplaySource(SdrSource):
|
|||||||
|
|
||||||
class AirspySource(SdrSource):
|
class AirspySource(SdrSource):
|
||||||
def getCommand(self):
|
def getCommand(self):
|
||||||
frequency = self.props["center_freq"] / 1e6
|
frequency = self.props["tuner_freq"] / 1e6
|
||||||
command = "airspy_rx"
|
command = "airspy_rx"
|
||||||
command += " -f{0}".format(frequency)
|
command += " -f{0}".format(frequency)
|
||||||
command += " -r /dev/stdout -a{samp_rate} -g {rf_gain}"
|
command += " -r /dev/stdout -a{samp_rate} -g {rf_gain}"
|
||||||
|
Loading…
Reference in New Issue
Block a user