140 lines
4.7 KiB
Python
140 lines
4.7 KiB
Python
import subprocess
|
|
import time
|
|
import os
|
|
import code
|
|
|
|
class dsp_plugin:
|
|
|
|
def __init__(self):
|
|
self.samp_rate = 250000
|
|
self.output_rate = 44100 #this is default, and cannot be set at the moment
|
|
self.fft_size = 1024
|
|
self.fft_fps = 5
|
|
self.offset_freq = 0
|
|
self.low_cut = -4000
|
|
self.high_cut = 4000
|
|
self.bpf_transition_bw = 320 #Hz, and this is a constant
|
|
self.ddc_transition_bw_rate = 0.15 # of the IF sample rate
|
|
self.running = False
|
|
chain_begin="nc localhost 4951 | csdr convert_u8_f | 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 | "
|
|
self.chains = {
|
|
"nfm" : chain_begin + "csdr fmdemod_quadri_cf | csdr limit_ff | csdr fractional_decimator_ff {last_decimation} | csdr deemphasis_nfm_ff 44100 | csdr fastagc_ff | csdr convert_f_i16",
|
|
"am" : chain_begin + "csdr amdemod_cf | csdr fastdcblock_ff | csdr fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_i16",
|
|
"ssb" : chain_begin + "csdr realpart_cf | csdr fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_i16",
|
|
"fft" : "nc -vv localhost 4951 | csdr convert_u8_f | csdr fft_cc {fft_size} {fft_block_size} | csdr logpower_cf -70"
|
|
}
|
|
self.demodulator = "nfm"
|
|
self.name = "csdr"
|
|
try:
|
|
subprocess.Popen("nc",stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
|
except:
|
|
print "[openwebrx-plugin:csdr] error: netcat not found, please install netcat!"
|
|
|
|
def set_samp_rate(self,samp_rate):
|
|
#to change this, restart is required
|
|
self.samp_rate=samp_rate
|
|
self.decimation=1
|
|
while self.samp_rate/(self.decimation+1)>self.output_rate:
|
|
self.decimation+=1
|
|
self.last_decimation=float(self.if_samp_rate())/self.output_rate
|
|
|
|
def if_samp_rate(self):
|
|
return self.samp_rate/self.decimation
|
|
|
|
def get_name(self):
|
|
return self.name
|
|
|
|
def get_output_rate(self):
|
|
return self.output_rate
|
|
|
|
|
|
def set_demodulator(self,demodulator):
|
|
#to change this, restart is required
|
|
self.demodulator=demodulator
|
|
|
|
def set_fft_size(self,fft_size):
|
|
#to change this, restart is required
|
|
self.fft_size=fft_size
|
|
|
|
def set_fft_fps(self,fft_fps):
|
|
#to change this, restart is required
|
|
self.fft_fps=fft_fps
|
|
|
|
def fft_block_size(self):
|
|
return self.samp_rate/self.fft_fps
|
|
|
|
def set_offset_freq(self,offset_freq):
|
|
self.offset_freq=offset_freq
|
|
if self.running:
|
|
self.shift_pipe_file.write("%g\n"%(-float(self.offset_freq)/self.samp_rate))
|
|
self.shift_pipe_file.flush()
|
|
|
|
def set_bpf(self,low_cut,high_cut):
|
|
self.low_cut=low_cut
|
|
self.high_cut=high_cut
|
|
if self.running:
|
|
self.bpf_pipe_file.write( "%g %g\n"%(float(self.low_cut)/self.if_samp_rate(), float(self.high_cut)/self.if_samp_rate()) )
|
|
self.bpf_pipe_file.flush()
|
|
|
|
def get_bpf(self):
|
|
return [self.low_cut, self.high_cut]
|
|
|
|
def mkfifo(self,path):
|
|
try:
|
|
os.unlink(path)
|
|
except:
|
|
pass
|
|
os.mkfifo(path)
|
|
|
|
def ddc_transition_bw(self):
|
|
return self.ddc_transition_bw_rate*(self.if_samp_rate()/float(self.samp_rate))
|
|
|
|
def start(self):
|
|
command_base=self.chains[self.demodulator]
|
|
|
|
#create control pipes for csdr
|
|
pipe_base_path="/tmp/openwebrx_pipe_{myid}_".format(myid=id(self))
|
|
self.bpf_pipe = self.shift_pipe = None
|
|
if "{bpf_pipe}" in command_base:
|
|
self.bpf_pipe=pipe_base_path+"bpf"
|
|
self.mkfifo(self.bpf_pipe)
|
|
if "{shift_pipe}" in command_base:
|
|
self.shift_pipe=pipe_base_path+"shift"
|
|
self.mkfifo(self.shift_pipe)
|
|
|
|
#run the command
|
|
command=command_base.format(bpf_pipe=self.bpf_pipe,shift_pipe=self.shift_pipe,decimation=self.decimation,last_decimation=self.last_decimation,fft_size=self.fft_size,fft_block_size=self.fft_block_size(),bpf_transition_bw=float(self.bpf_transition_bw)/self.if_samp_rate(),ddc_transition_bw=self.ddc_transition_bw())
|
|
print "[openwebrx-dsp-plugin:csdr] Command =",command
|
|
#code.interact(local=locals())
|
|
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
|
|
self.running = True
|
|
|
|
#open control pipes for csdr and send initialization data
|
|
if self.bpf_pipe != None:
|
|
self.bpf_pipe_file=open(self.bpf_pipe,"w")
|
|
self.set_bpf(self.low_cut,self.high_cut)
|
|
if self.shift_pipe != None:
|
|
self.shift_pipe_file=open(self.shift_pipe,"w")
|
|
self.set_offset_freq(self.offset_freq)
|
|
|
|
def read(self,size):
|
|
return self.process.stdout.read(size)
|
|
|
|
def stop(self):
|
|
if(self.process!=None):return # returns None while subprocess is running
|
|
while(self.process.poll()==None):
|
|
self.process.kill()
|
|
time.sleep(0.1)
|
|
os.unlink(self.bpf_pipe)
|
|
os.unlink(self.shift_pipe)
|
|
self.running = False
|
|
|
|
def restart(self):
|
|
self.stop()
|
|
self.start()
|
|
|
|
def __del__(self):
|
|
self.stop()
|
|
del(self.process)
|
|
|