add airspy source; fix offset tuning
This commit is contained in:
parent
5375580104
commit
de51e266f6
@ -106,7 +106,7 @@ sdrs = {
|
||||
"type": "rtl_sdr",
|
||||
"ppm": 0,
|
||||
# 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,
|
||||
"profiles": {
|
||||
"70cm": {
|
||||
|
@ -1046,7 +1046,7 @@ function on_ws_recv(evt) {
|
||||
starting_mod = config['start_mod'];
|
||||
starting_offset_frequency = config['start_offset_freq'];
|
||||
bandwidth = config['samp_rate'];
|
||||
center_freq = config['center_freq'] + config['lfo_offset'];
|
||||
center_freq = config['center_freq'];
|
||||
fft_size = config['fft_size'];
|
||||
fft_fps = config['fft_fps'];
|
||||
var audio_compression = config['audio_compression'];
|
||||
|
@ -57,7 +57,6 @@ class OpenWebRxReceiverClient(Client):
|
||||
"waterfall_min_level",
|
||||
"waterfall_max_level",
|
||||
"waterfall_auto_level_margin",
|
||||
"lfo_offset",
|
||||
"samp_rate",
|
||||
"fft_size",
|
||||
"fft_fps",
|
||||
|
@ -20,11 +20,12 @@ class FeatureDetector(object):
|
||||
features = {
|
||||
"core": ["csdr", "nmux", "nc"],
|
||||
"rtl_sdr": ["rtl_sdr"],
|
||||
"rtl_sdr_connector": ["owrx_connector"],
|
||||
"rtl_sdr_connector": ["rtl_connector"],
|
||||
"sdrplay": ["rx_tools"],
|
||||
"sdrplay_connector": ["owrx_connector"],
|
||||
"sdrplay_connector": ["soapy_connector"],
|
||||
"hackrf": ["hackrf_transfer"],
|
||||
"airspy": ["airspy_rx"],
|
||||
"airspy_connector": ["soapy_connector"],
|
||||
"digital_voice_digiham": ["digiham", "sox"],
|
||||
"digital_voice_dsd": ["dsd", "sox", "digiham"],
|
||||
"wsjt-x": ["wsjtx", "sox"],
|
||||
@ -194,39 +195,39 @@ class FeatureDetector(object):
|
||||
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
|
||||
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
|
||||
"""
|
||||
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):
|
||||
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
|
||||
|
||||
return reduce(
|
||||
and_,
|
||||
map(
|
||||
check_owrx_connector_version,
|
||||
[
|
||||
"rtl_connector",
|
||||
],
|
||||
),
|
||||
True,
|
||||
)
|
||||
You can get it here: https://github.com/jketterl/owrx_connector
|
||||
"""
|
||||
return self._check_connector("soapy_connector")
|
||||
|
||||
def has_dsd(self):
|
||||
"""
|
||||
|
@ -136,7 +136,7 @@ class SdrSource(object):
|
||||
self.busyState = SdrSource.BUSYSTATE_IDLE
|
||||
|
||||
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 restart(name, value):
|
||||
@ -190,6 +190,14 @@ class SdrSource(object):
|
||||
def useNmux(self):
|
||||
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):
|
||||
self.modificationLock.acquire()
|
||||
if self.monitor:
|
||||
@ -199,7 +207,7 @@ class SdrSource(object):
|
||||
props = self.rtlProps
|
||||
|
||||
cmd = self.getCommand().format(
|
||||
**props.collect(*self.getEventNames()).__dict__()
|
||||
**self.getCommandValues()
|
||||
)
|
||||
|
||||
format_conversion = self.getFormatConversion()
|
||||
@ -447,8 +455,11 @@ class ConnectorSource(SdrSource):
|
||||
def reconfigure(prop, value):
|
||||
if self.monitor is None:
|
||||
return
|
||||
logger.debug("sending property change over control socket: {0} changed to {1}".format(prop, value))
|
||||
self.controlSocket.sendall("{prop}:{value}\n".format(prop=prop, value=value).encode())
|
||||
v = value
|
||||
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)
|
||||
|
||||
@ -472,27 +483,45 @@ class ConnectorSource(SdrSource):
|
||||
|
||||
class RtlSdrConnectorSource(ConnectorSource):
|
||||
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):
|
||||
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}"
|
||||
|
||||
|
||||
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}\""
|
||||
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}"
|
||||
if self.rtlProps["iqswap"]:
|
||||
cmd += " -i"
|
||||
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):
|
||||
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):
|
||||
return "csdr convert_u8_f"
|
||||
@ -500,7 +529,7 @@ class RtlSdrSource(SdrSource):
|
||||
|
||||
class HackrfSource(SdrSource):
|
||||
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):
|
||||
return "csdr convert_s8_f"
|
||||
@ -508,7 +537,7 @@ class HackrfSource(SdrSource):
|
||||
|
||||
class SdrplaySource(SdrSource):
|
||||
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"}
|
||||
gains = [
|
||||
"{0}={{{1}}}".format(gainMap[name], name)
|
||||
@ -528,7 +557,7 @@ class SdrplaySource(SdrSource):
|
||||
|
||||
class AirspySource(SdrSource):
|
||||
def getCommand(self):
|
||||
frequency = self.props["center_freq"] / 1e6
|
||||
frequency = self.props["tuner_freq"] / 1e6
|
||||
command = "airspy_rx"
|
||||
command += " -f{0}".format(frequency)
|
||||
command += " -r /dev/stdout -a{samp_rate} -g {rf_gain}"
|
||||
|
Loading…
Reference in New Issue
Block a user