Merge branch 'develop' into pycsdr
This commit is contained in:
38
csdr/csdr.py
38
csdr/csdr.py
@ -4,7 +4,7 @@ OpenWebRX csdr plugin: do the signal processing with csdr
|
||||
This file is part of OpenWebRX,
|
||||
an open-source SDR receiver software with a web UI.
|
||||
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
|
||||
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de>
|
||||
Copyright (c) 2019-2021 by Jakob Ketterl <dd5jfk@darc.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@ -211,10 +211,7 @@ class dsp(object):
|
||||
"csdr limit_ff",
|
||||
]
|
||||
chain += last_decimation_block
|
||||
chain += [
|
||||
"csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}",
|
||||
"csdr convert_f_s16"
|
||||
]
|
||||
chain += ["csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}", "csdr convert_f_s16"]
|
||||
elif self.isDigitalVoice(which):
|
||||
chain += ["csdr fmdemod_quadri_cf"]
|
||||
chain += last_decimation_block
|
||||
@ -473,7 +470,9 @@ class dsp(object):
|
||||
def set_secondary_offset_freq(self, value):
|
||||
self.secondary_offset_freq = value
|
||||
if self.secondary_processes_running and self.has_pipe("secondary_shift_pipe"):
|
||||
self.pipes["secondary_shift_pipe"].write("%g\n" % (-float(self.secondary_offset_freq) / self.if_samp_rate()))
|
||||
self.pipes["secondary_shift_pipe"].write(
|
||||
"%g\n" % (-float(self.secondary_offset_freq) / self.if_samp_rate())
|
||||
)
|
||||
|
||||
def stop_secondary_demodulator(self):
|
||||
if not self.secondary_processes_running:
|
||||
@ -548,25 +547,20 @@ class dsp(object):
|
||||
self.restart()
|
||||
|
||||
def calculate_decimation(self):
|
||||
(self.decimation, self.last_decimation, _) = self.get_decimation(self.samp_rate, self.get_audio_rate())
|
||||
(self.decimation, self.last_decimation) = self.get_decimation(self.samp_rate, self.get_audio_rate())
|
||||
|
||||
def get_decimation(self, input_rate, output_rate):
|
||||
decimation = 1
|
||||
correction = 1
|
||||
target_rate = output_rate
|
||||
# wideband fm has a much higher frequency deviation (75kHz).
|
||||
# we cannot cover this if we immediately decimate to the sample rate the audio will have later on, so we need
|
||||
# to compensate here.
|
||||
# the factor of 6 is by experimentation only, with a minimum audio rate of 36kHz (enforced by the client)
|
||||
# this allows us to cover at least +/- 108kHz of frequency spectrum (may be higher, but that's the worst case).
|
||||
# the correction factor is automatically compensated for by the secondary decimation stage, which comes
|
||||
# after the demodulator.
|
||||
if self.get_demodulator() == "wfm":
|
||||
correction = 6
|
||||
while input_rate / (decimation + 1) >= output_rate * correction:
|
||||
if self.get_demodulator() == "wfm" and output_rate < 200000:
|
||||
target_rate = 200000
|
||||
while input_rate / (decimation + 1) >= target_rate:
|
||||
decimation += 1
|
||||
fraction = float(input_rate / decimation) / output_rate
|
||||
intermediate_rate = input_rate / decimation
|
||||
return decimation, fraction, intermediate_rate
|
||||
return decimation, fraction
|
||||
|
||||
def if_samp_rate(self):
|
||||
return self.samp_rate / self.decimation
|
||||
@ -601,7 +595,7 @@ class dsp(object):
|
||||
demodulator = self.get_secondary_demodulator()
|
||||
return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w"]
|
||||
|
||||
def isJs8(self, demodulator = None):
|
||||
def isJs8(self, demodulator=None):
|
||||
if demodulator is None:
|
||||
demodulator = self.get_secondary_demodulator()
|
||||
return demodulator == "js8"
|
||||
@ -712,7 +706,11 @@ class dsp(object):
|
||||
def set_squelch_level(self, squelch_level):
|
||||
self.squelch_level = squelch_level
|
||||
# no squelch required on digital voice modes
|
||||
actual_squelch = -150 if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() else self.squelch_level
|
||||
actual_squelch = (
|
||||
-150
|
||||
if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV()
|
||||
else self.squelch_level
|
||||
)
|
||||
if self.running:
|
||||
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
|
||||
|
||||
@ -887,6 +885,7 @@ class dsp(object):
|
||||
self.start_secondary_demodulator()
|
||||
|
||||
if self.has_pipe("smeter_pipe"):
|
||||
|
||||
def read_smeter():
|
||||
raw = self.pipes["smeter_pipe"].readline()
|
||||
if len(raw) == 0:
|
||||
@ -896,6 +895,7 @@ class dsp(object):
|
||||
|
||||
self.output.send_output("smeter", read_smeter)
|
||||
if self.has_pipe("meta_pipe"):
|
||||
|
||||
def read_meta():
|
||||
raw = self.pipes["meta_pipe"].readline()
|
||||
if len(raw) == 0:
|
||||
|
@ -42,6 +42,7 @@ class Pipe(object):
|
||||
immediately here), resulting in empty reads until data is available. This is handled specially in the
|
||||
ReadingPipe class.
|
||||
"""
|
||||
|
||||
def opener(path, flags):
|
||||
fd = os.open(path, flags | os.O_NONBLOCK)
|
||||
os.set_blocking(fd, True)
|
||||
@ -88,7 +89,7 @@ class WritingPipe(Pipe):
|
||||
except OSError as error:
|
||||
# ENXIO = FIFO has not been opened for reading
|
||||
if error.errno == 6:
|
||||
time.sleep(.1)
|
||||
time.sleep(0.1)
|
||||
retries += 1
|
||||
else:
|
||||
raise
|
||||
|
Reference in New Issue
Block a user