Retabbed python code and added secondary demodulators
This commit is contained in:
parent
ffe141f2a0
commit
2b11e0f94a
194
plugins/dsp/csdr/plugin.py
Normal file → Executable file
194
plugins/dsp/csdr/plugin.py
Normal file → Executable file
@ -40,6 +40,7 @@ class dsp_plugin:
|
|||||||
self.bpf_transition_bw = 320 #Hz, and this is a constant
|
self.bpf_transition_bw = 320 #Hz, and this is a constant
|
||||||
self.ddc_transition_bw_rate = 0.15 # of the IF sample rate
|
self.ddc_transition_bw_rate = 0.15 # of the IF sample rate
|
||||||
self.running = False
|
self.running = False
|
||||||
|
self.secondary_processes_running = False
|
||||||
self.audio_compression = "none"
|
self.audio_compression = "none"
|
||||||
self.fft_compression = "none"
|
self.fft_compression = "none"
|
||||||
self.demodulator = "nfm"
|
self.demodulator = "nfm"
|
||||||
@ -52,6 +53,14 @@ class dsp_plugin:
|
|||||||
self.csdr_through = False
|
self.csdr_through = False
|
||||||
self.squelch_level = 0
|
self.squelch_level = 0
|
||||||
self.fft_averages = 50
|
self.fft_averages = 50
|
||||||
|
self.iqtee = False
|
||||||
|
self.iqtee2 = False
|
||||||
|
self.secondary_demodulator = None
|
||||||
|
self.secondary_fft_size = 1024
|
||||||
|
self.secondary_process_fft = None
|
||||||
|
self.secondary_process_demod = None
|
||||||
|
self.pipe_names=["bpf_pipe", "shift_pipe", "squelch_pipe", "smeter_pipe", "iqtee_pipe", "iqtee2_pipe"]
|
||||||
|
self.secondary_pipe_names=["secondary_shift_pipe"]
|
||||||
|
|
||||||
def chain(self,which):
|
def chain(self,which):
|
||||||
any_chain_base="nc -v 127.0.0.1 {nc_port} | "
|
any_chain_base="nc -v 127.0.0.1 {nc_port} | "
|
||||||
@ -67,6 +76,9 @@ class dsp_plugin:
|
|||||||
else:
|
else:
|
||||||
return fft_chain_base
|
return fft_chain_base
|
||||||
chain_begin=any_chain_base+"csdr shift_addition_cc --fifo {shift_pipe} | csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING | csdr bandpass_fir_fft_cc --fifo {bpf_pipe} {bpf_transition_bw} HAMMING | csdr squelch_and_smeter_cc --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 1 | "
|
chain_begin=any_chain_base+"csdr shift_addition_cc --fifo {shift_pipe} | csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING | csdr bandpass_fir_fft_cc --fifo {bpf_pipe} {bpf_transition_bw} HAMMING | csdr squelch_and_smeter_cc --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 1 | "
|
||||||
|
if self.secondary_demodulator:
|
||||||
|
chain_begin+="tee {iqtee_pipe} | "
|
||||||
|
chain_begin+="tee {iqtee_pipe2} | "
|
||||||
chain_end = ""
|
chain_end = ""
|
||||||
if self.audio_compression=="adpcm":
|
if self.audio_compression=="adpcm":
|
||||||
chain_end = " | csdr encode_ima_adpcm_i16_u8"
|
chain_end = " | csdr encode_ima_adpcm_i16_u8"
|
||||||
@ -74,6 +86,98 @@ class dsp_plugin:
|
|||||||
elif which == "am": return chain_begin + "csdr amdemod_cf | csdr fastdcblock_ff | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
elif which == "am": return chain_begin + "csdr amdemod_cf | csdr fastdcblock_ff | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
||||||
elif which == "ssb": return chain_begin + "csdr realpart_cf | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
elif which == "ssb": return chain_begin + "csdr realpart_cf | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
||||||
|
|
||||||
|
def secondary_chain(self, which):
|
||||||
|
secondary_chain_base="cat {input_pipe} | "
|
||||||
|
|
||||||
|
if which == "fft":
|
||||||
|
return secondary_chain_base+"csdr fft_cc {secondary_fft_size} {secondary_fft_block_size} | csdrr logpower_cf -70 | csdr fft_one_side_ff {secondary_fft_size}"
|
||||||
|
elif which == "bpsk31":
|
||||||
|
return secondary_chain_base+"""csdr dsb_fc | \
|
||||||
|
csdr shift_addition_cc {secondary_shift_pipe} | \
|
||||||
|
csdr REM fir_decimate_cc {secondary_decimation} | \
|
||||||
|
csdr bandpass_fir_fft_cc -{secondary_bpf_cutoff} {secondary_bpf_cutoff} {secondary_bpf_transition_bw} HAMMING | \
|
||||||
|
csdr simple_agc_cc 0.0001 0.5 | \
|
||||||
|
csdr matched_filter_cc COSINE 48 | \
|
||||||
|
csdr timing_recovery_cc EARLYLATE {secondary_samples_per_bits} --add_q | \
|
||||||
|
|
||||||
|
CSDR_FIXED_BUFSIZE=1 csdr realpart_cf | \
|
||||||
|
CSDR_FIXED_BUFSIZE=1 csdr binary_slicer_f_u8 | \
|
||||||
|
CSDR_FIXED_BUFSIZE=1 csdr differential_decoder_u8_u8 | \
|
||||||
|
CSDR_FIXED_BUFSIZE=1 csdr psk31_varicode_decoder_u8_u8
|
||||||
|
"""
|
||||||
|
|
||||||
|
def set_secondary_demodulator(self, what):
|
||||||
|
self.secondary_demodulator = what
|
||||||
|
|
||||||
|
def secondary_fft_block_size(self):
|
||||||
|
return (self.samp_rate/self.decimation)/self.fft_fps
|
||||||
|
|
||||||
|
def secondary_decimation(self, which):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def secondary_bpf_cutoff(self, which):
|
||||||
|
if self.secondary_demodulator == "bpsk31":
|
||||||
|
return 31.25 / self.if_samp_rate()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def secondary_bpf_transition_bw(self, which):
|
||||||
|
if self.secondary_demodulator == "bpsk31":
|
||||||
|
return (31.25 / 2) * self.if_samp_rate()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def start_secondary_demodulator(self):
|
||||||
|
if(not self.secondary_demodulator): return
|
||||||
|
secondary_command_fft=secondary_chain("fft")
|
||||||
|
secondary_command_fft=secondary_command_fft.format( \
|
||||||
|
input_pipe=self.iqtee_pipe, \
|
||||||
|
secondary_fft_size=self.secondary_fft_size, \
|
||||||
|
secondary_fft_block_size=self.secondary_fft_block_size(), \
|
||||||
|
)
|
||||||
|
secondary_command_demod=self.secondary_chain(self.secondary_demodulator)
|
||||||
|
secondary_command_demod.format( \
|
||||||
|
input_pipe=self.iqtee2_pipe, \
|
||||||
|
secondary_shift_pipe=self.secondary_shift_pipe, \
|
||||||
|
secondary_decimation=self.secondary_decimation(self.secondary_demodulator), \
|
||||||
|
secondary_samples_per_bits=self.secondary_samples_per_bits(self.secondary_demodulator), \
|
||||||
|
secondary_bpf_cutoff=self.secondary_bpf_cutoff(self.secondary_demodulator), \
|
||||||
|
secondary_bpf_transition_bw=self.secondary_bpf_transition_bw(self.secondary_demodulator)
|
||||||
|
)
|
||||||
|
try_create_pipes(secondary_command_demod + secondary_command_fft, self.secondary_pipe_names)
|
||||||
|
|
||||||
|
print "[openwebrx-dsp-plugin:csdr] secondary command (fft) =", secondary_command_fft
|
||||||
|
print "[openwebrx-dsp-plugin:csdr] secondary command (demod) =", secondary_command_demod
|
||||||
|
#code.interact(local=locals())
|
||||||
|
my_env=os.environ.copy()
|
||||||
|
#if self.csdr_dynamic_bufsize: my_env["CSDR_DYNAMIC_BUFSIZE_ON"]="1";
|
||||||
|
if self.csdr_print_bufsizes: my_env["CSDR_PRINT_BUFSIZES"]="1";
|
||||||
|
self.secondary_process_fft = subprocess.Popen(secondary_command_fft, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env)
|
||||||
|
self.secondary_process_demod = subprocess.Popen(secondary_command_demod, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env)
|
||||||
|
self.secondary_processes_running = True
|
||||||
|
|
||||||
|
#open control pipes for csdr and send initialization data
|
||||||
|
if self.secondary_shift_pipe != None:
|
||||||
|
self.secondary_shift_pipe_file=open(self.secondary_shift_pipe,"w")
|
||||||
|
self.set_secondary_offset_freq(self.secondary_offset_freq)
|
||||||
|
|
||||||
|
def set_secondary_offset_freq(self, value):
|
||||||
|
self.secondary_offset_freq=value
|
||||||
|
if self.secondary_processes_running:
|
||||||
|
self.secondary_shift_pipe_file.write("%g\n"%(-float(self.secondary_offset_freq)/self.if_samp_rate()))
|
||||||
|
self.secondary_shift_pipe_file.flush()
|
||||||
|
|
||||||
|
def stop_secondary_demodulator(self):
|
||||||
|
if self.secondary_processes_running == False: return
|
||||||
|
self.try_delete_pipes(self.secondary_pipe_names)
|
||||||
|
if self.secondary_process_fft: os.killpg(os.getpgid(self.secondary_process_fft.pid), signal.SIGTERM)
|
||||||
|
if self.secondary_process_demod: os.killpg(os.getpgid(self.secondary_process_demod.pid), signal.SIGTERM)
|
||||||
|
self.secondary_processes_running = False
|
||||||
|
|
||||||
|
def read_secondary_demod(self, size):
|
||||||
|
return self.secondary_process_demod.stdout.read(size)
|
||||||
|
|
||||||
|
def read_secondary_fft(self, size):
|
||||||
|
return self.secondary_process_fft.stdout.read(size)
|
||||||
|
|
||||||
def set_audio_compression(self,what):
|
def set_audio_compression(self,what):
|
||||||
self.audio_compression = what
|
self.audio_compression = what
|
||||||
|
|
||||||
@ -168,24 +272,49 @@ class dsp_plugin:
|
|||||||
def ddc_transition_bw(self):
|
def ddc_transition_bw(self):
|
||||||
return self.ddc_transition_bw_rate*(self.if_samp_rate()/float(self.samp_rate))
|
return self.ddc_transition_bw_rate*(self.if_samp_rate()/float(self.samp_rate))
|
||||||
|
|
||||||
|
def try_create_pipes(self, pipe_names, command_base):
|
||||||
|
for pipe_name in pipe_names:
|
||||||
|
if "{"+pipe_name+"}" in command_base:
|
||||||
|
setattr(self, pipe_name, self.pipe_base_path+pipe_name)
|
||||||
|
self.mkfifo(getattr(self, pipe_name))
|
||||||
|
else:
|
||||||
|
setattr(self, pipe_name, None)
|
||||||
|
|
||||||
|
def try_delete_pipes(self, pipe_names):
|
||||||
|
for pipe_name in pipe_names:
|
||||||
|
pipe_path = getattr(self,pipe_name,None)
|
||||||
|
if pipe_path:
|
||||||
|
try: os.unlink(pipe_path)
|
||||||
|
except: print "[openwebrx-dsp-plugin:csdr] try_delete_pipes() :: unlink failed: " + pipe_path
|
||||||
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
command_base=self.chain(self.demodulator)
|
command_base=self.chain(self.demodulator)
|
||||||
|
|
||||||
#create control pipes for csdr
|
#create control pipes for csdr
|
||||||
pipe_base_path="/tmp/openwebrx_pipe_{myid}_".format(myid=id(self))
|
self.pipe_base_path="/tmp/openwebrx_pipe_{myid}_".format(myid=id(self))
|
||||||
self.bpf_pipe = self.shift_pipe = self.squelch_pipe = self.smeter_pipe = None
|
# self.bpf_pipe = self.shift_pipe = self.squelch_pipe = self.smeter_pipe = None
|
||||||
if "{bpf_pipe}" in command_base:
|
|
||||||
self.bpf_pipe=pipe_base_path+"bpf"
|
self.try_create_pipes(self.pipe_names, command_base)
|
||||||
self.mkfifo(self.bpf_pipe)
|
|
||||||
if "{shift_pipe}" in command_base:
|
# if "{bpf_pipe}" in command_base:
|
||||||
self.shift_pipe=pipe_base_path+"shift"
|
# self.bpf_pipe=pipe_base_path+"bpf"
|
||||||
self.mkfifo(self.shift_pipe)
|
# self.mkfifo(self.bpf_pipe)
|
||||||
if "{squelch_pipe}" in command_base:
|
# if "{shift_pipe}" in command_base:
|
||||||
self.squelch_pipe=pipe_base_path+"squelch"
|
# self.shift_pipe=pipe_base_path+"shift"
|
||||||
self.mkfifo(self.squelch_pipe)
|
# self.mkfifo(self.shift_pipe)
|
||||||
if "{smeter_pipe}" in command_base:
|
# if "{squelch_pipe}" in command_base:
|
||||||
self.smeter_pipe=pipe_base_path+"smeter"
|
# self.squelch_pipe=pipe_base_path+"squelch"
|
||||||
self.mkfifo(self.smeter_pipe)
|
# self.mkfifo(self.squelch_pipe)
|
||||||
|
# if "{smeter_pipe}" in command_base:
|
||||||
|
# self.smeter_pipe=pipe_base_path+"smeter"
|
||||||
|
# self.mkfifo(self.smeter_pipe)
|
||||||
|
# if "{iqtee_pipe}" in command_base:
|
||||||
|
# self.iqtee_pipe=pipe_base_path+"iqtee"
|
||||||
|
# self.mkfifo(self.iqtee_pipe)
|
||||||
|
# if "{iqtee2_pipe}" in command_base:
|
||||||
|
# self.iqtee2_pipe=pipe_base_path+"iqtee2"
|
||||||
|
# self.mkfifo(self.iqtee2_pipe)
|
||||||
|
|
||||||
#run the command
|
#run the command
|
||||||
command=command_base.format( bpf_pipe=self.bpf_pipe, shift_pipe=self.shift_pipe, decimation=self.decimation, \
|
command=command_base.format( bpf_pipe=self.bpf_pipe, shift_pipe=self.shift_pipe, decimation=self.decimation, \
|
||||||
@ -216,11 +345,14 @@ class dsp_plugin:
|
|||||||
self.smeter_pipe_file=open(self.smeter_pipe,"r")
|
self.smeter_pipe_file=open(self.smeter_pipe,"r")
|
||||||
fcntl.fcntl(self.smeter_pipe_file, fcntl.F_SETFL, os.O_NONBLOCK)
|
fcntl.fcntl(self.smeter_pipe_file, fcntl.F_SETFL, os.O_NONBLOCK)
|
||||||
|
|
||||||
|
self.start_secondary_demodulator()
|
||||||
|
|
||||||
def read(self,size):
|
def read(self,size):
|
||||||
return self.process.stdout.read(size)
|
return self.process.stdout.read(size)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
|
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
|
||||||
|
self.stop_secondary_demodulator()
|
||||||
#if(self.process.poll()!=None):return # returns None while subprocess is running
|
#if(self.process.poll()!=None):return # returns None while subprocess is running
|
||||||
#while(self.process.poll()==None):
|
#while(self.process.poll()==None):
|
||||||
# #self.process.kill()
|
# #self.process.kill()
|
||||||
@ -228,18 +360,28 @@ class dsp_plugin:
|
|||||||
# os.killpg(self.process.pid, signal.SIGTERM)
|
# os.killpg(self.process.pid, signal.SIGTERM)
|
||||||
#
|
#
|
||||||
# time.sleep(0.1)
|
# time.sleep(0.1)
|
||||||
if self.bpf_pipe:
|
|
||||||
try: os.unlink(self.bpf_pipe)
|
self.try_delete_pipes(self.pipe_names)
|
||||||
except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
|
||||||
if self.shift_pipe:
|
# if self.bpf_pipe:
|
||||||
try: os.unlink(self.shift_pipe)
|
# try: os.unlink(self.bpf_pipe)
|
||||||
except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.shift_pipe
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
||||||
if self.squelch_pipe:
|
# if self.shift_pipe:
|
||||||
try: os.unlink(self.squelch_pipe)
|
# try: os.unlink(self.shift_pipe)
|
||||||
except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.squelch_pipe
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.shift_pipe
|
||||||
if self.smeter_pipe:
|
# if self.squelch_pipe:
|
||||||
try: os.unlink(self.smeter_pipe)
|
# try: os.unlink(self.squelch_pipe)
|
||||||
except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.smeter_pipe
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.squelch_pipe
|
||||||
|
# if self.smeter_pipe:
|
||||||
|
# try: os.unlink(self.smeter_pipe)
|
||||||
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.smeter_pipe
|
||||||
|
# if self.iqtee_pipe:
|
||||||
|
# try: os.unlink(self.iqtee_pipe)
|
||||||
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.iqtee_pipe
|
||||||
|
# if self.iqtee2_pipe:
|
||||||
|
# try: os.unlink(self.iqtee2_pipe)
|
||||||
|
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.iqtee2_pipe
|
||||||
|
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user