add fft and catch exceptions
This commit is contained in:
parent
8c98a8be52
commit
8f79322244
|
@ -36,9 +36,11 @@ GNUPLOT = '/usr/bin/gnuplot'
|
|||
class wrap_gp(object):
|
||||
def __init__(self, sps=_def_sps):
|
||||
self.sps = sps
|
||||
self.center_freq = None
|
||||
self.width = None
|
||||
self.buf = []
|
||||
|
||||
self.attach_gp()
|
||||
self.buf = []
|
||||
|
||||
def attach_gp(self):
|
||||
args = (GNUPLOT, '-noraise')
|
||||
|
@ -80,29 +82,51 @@ class wrap_gp(object):
|
|||
self.buf = []
|
||||
plots.append('"-" with dots')
|
||||
elif mode == 'fft':
|
||||
ffbuf = np.fft.fft(self.buf)
|
||||
for b in ffbuf:
|
||||
s += '%f\n' % (b.real**2 + b.imag**2)
|
||||
ffbuf = np.fft.fft(self.buf * np.blackman(BUFSZ)) / (0.42 * BUFSZ)
|
||||
ffbuf = np.fft.fftshift(ffbuf)
|
||||
for i in xrange(len(ffbuf)):
|
||||
if self.center_freq and self.width:
|
||||
f = (self.center_freq - self.width / 2.0) / 1e6
|
||||
w = self.width / 1e6
|
||||
s += '%f\t%f\n' % (f + i*(w/BUFSZ), 20 * np.log10(np.abs(ffbuf[i])))
|
||||
else:
|
||||
s += '%f\n' % (20 * np.log10(np.abs(ffbuf[i])))
|
||||
s += 'e\n'
|
||||
self.buf = []
|
||||
plots.append('"-" with lines')
|
||||
self.buf = []
|
||||
|
||||
h= 'set terminal x11 noraise\n'
|
||||
h+= 'set size square\n'
|
||||
h += 'set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb"black"\n'
|
||||
background = 'set object 1 circle from screen 0,0 to screen 1,1 fillcolor rgb"black"\n'
|
||||
h+= 'set key off\n'
|
||||
if mode == 'constellation':
|
||||
h += background
|
||||
h+= 'set size square\n'
|
||||
h+= 'set xrange [-1:1]\n'
|
||||
h+= 'set yrange [-1:1]\n'
|
||||
elif mode == 'eye':
|
||||
h += background
|
||||
h+= 'set yrange [-4:4]\n'
|
||||
elif mode == 'symbol':
|
||||
h += background
|
||||
h+= 'set yrange [-4:4]\n'
|
||||
elif mode == 'fft':
|
||||
h+= 'set yrange [-100:0]\n'
|
||||
h+= 'set grid\n'
|
||||
if self.center_freq:
|
||||
h += 'set title "%f"\n' % (self.center_freq / 1e6)
|
||||
dat = '%splot %s\n%s' % (h, ','.join(plots), s)
|
||||
self.gp.stdin.write(dat)
|
||||
return consumed
|
||||
|
||||
def set_center_freq(self, f):
|
||||
sys.stderr.write('set_center_freq: %s\n' % f)
|
||||
self.center_freq = f
|
||||
|
||||
def set_width(self, w):
|
||||
sys.stderr.write('set_width: %f\n' % w)
|
||||
self.width = w
|
||||
|
||||
class eye_sink_f(gr.sync_block):
|
||||
"""
|
||||
"""
|
||||
|
@ -152,15 +176,25 @@ class fft_sink_c(gr.sync_block):
|
|||
out_sig=None)
|
||||
self.debug = debug
|
||||
self.gnuplot = wrap_gp()
|
||||
self.skip = 0
|
||||
|
||||
def work(self, input_items, output_items):
|
||||
in0 = input_items[0]
|
||||
self.gnuplot.plot(in0, 512, mode='fft')
|
||||
self.skip += 1
|
||||
if self.skip == 50:
|
||||
self.skip = 0
|
||||
in0 = input_items[0]
|
||||
self.gnuplot.plot(in0, 512, mode='fft')
|
||||
return len(input_items[0])
|
||||
|
||||
def kill(self):
|
||||
self.gnuplot.kill()
|
||||
|
||||
def set_center_freq(self, f):
|
||||
self.gnuplot.set_center_freq(f)
|
||||
|
||||
def set_width(self, w):
|
||||
self.gnuplot.set_width(w)
|
||||
|
||||
class symbol_sink_f(gr.sync_block):
|
||||
"""
|
||||
"""
|
||||
|
|
|
@ -296,3 +296,6 @@ class p25_demod_cb(p25_demod_base):
|
|||
elif src == 'mixer':
|
||||
self.connect(self.mixer, sink)
|
||||
self.complex_sink = [self.mixer, sink]
|
||||
elif src == 'src':
|
||||
self.connect(self, sink)
|
||||
self.complex_sink = [self, sink]
|
||||
|
|
|
@ -33,6 +33,7 @@ import numpy
|
|||
import time
|
||||
import re
|
||||
import json
|
||||
import traceback
|
||||
try:
|
||||
import Hamlib
|
||||
except:
|
||||
|
@ -95,7 +96,7 @@ class p25_rx_block (gr.top_block):
|
|||
parser.add_option("-c", "--calibration", type="eng_float", default=0.0, help="USRP offset or audio IF frequency", metavar="Hz")
|
||||
parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.04, help="value of alpha for Costas loop", metavar="Hz")
|
||||
parser.add_option("-D", "--demod-type", type="choice", default="cqpsk", choices=('cqpsk', 'fsk4'), help="cqpsk | fsk4")
|
||||
parser.add_option("-P", "--plot-mode", type="choice", default=None, choices=(None, 'constellation', 'symbol', 'datascope'), help="constellation | symbol | datascope")
|
||||
parser.add_option("-P", "--plot-mode", type="choice", default=None, choices=(None, 'constellation', 'fft', 'symbol', 'datascope'), help="constellation | fft | symbol | datascope")
|
||||
parser.add_option("-f", "--frequency", type="eng_float", default=0.0, help="USRP center frequency", metavar="Hz")
|
||||
parser.add_option("-F", "--ifile", type="string", default=None, help="read input from complex capture file")
|
||||
parser.add_option("-H", "--hamlib-model", type="int", default=None, help="specify model for hamlib")
|
||||
|
@ -128,6 +129,7 @@ class p25_rx_block (gr.top_block):
|
|||
self.baseband_input = False
|
||||
self.rtl_found = False
|
||||
self.channel_rate = options.sample_rate
|
||||
self.fft_sink = None
|
||||
|
||||
self.src = None
|
||||
if not options.input:
|
||||
|
@ -202,10 +204,8 @@ class p25_rx_block (gr.top_block):
|
|||
print 'Ready for GDB to attach (pid = %d)' % (os.getpid(),)
|
||||
raw_input("Press 'Enter' to continue...")
|
||||
|
||||
# attach terminal thread
|
||||
self.input_q = gr.msg_queue(10)
|
||||
self.output_q = gr.msg_queue(10)
|
||||
self.terminal = curses_terminal(self.input_q, self.output_q)
|
||||
|
||||
# configure specified data source
|
||||
if options.input:
|
||||
|
@ -221,6 +221,9 @@ class p25_rx_block (gr.top_block):
|
|||
else:
|
||||
pass
|
||||
|
||||
# attach terminal thread
|
||||
self.terminal = curses_terminal(self.input_q, self.output_q)
|
||||
|
||||
# setup common flow graph elements
|
||||
#
|
||||
def __build_graph(self, source, capture_rate):
|
||||
|
@ -285,6 +288,12 @@ class p25_rx_block (gr.top_block):
|
|||
self.symbol_sink = symbol_sink_f()
|
||||
self.demod.connect_float(self.symbol_sink)
|
||||
self.kill_sink = self.symbol_sink
|
||||
elif self.options.plot_mode == 'fft':
|
||||
self.fft_sink = fft_sink_c()
|
||||
self.spectrum_decim = filter.rational_resampler_ccf(1, self.options.decim_amt)
|
||||
self.connect(self.spectrum_decim, self.fft_sink)
|
||||
self.demod.connect_complex('src', self.spectrum_decim)
|
||||
self.kill_sink = self.fft_sink
|
||||
elif self.options.plot_mode == 'datascope':
|
||||
assert self.options.demod_type == 'fsk4' ## datascope requires fsk4 demod-type
|
||||
self.eye_sink = eye_sink_f(sps=10)
|
||||
|
@ -441,7 +450,11 @@ class p25_rx_block (gr.top_block):
|
|||
return False
|
||||
tune_freq = target_freq + self.options.calibration + self.options.offset
|
||||
r = self.src.set_center_freq(tune_freq)
|
||||
|
||||
|
||||
if self.fft_sink:
|
||||
self.fft_sink.set_center_freq(tune_freq)
|
||||
self.fft_sink.set_width(self.options.sample_rate)
|
||||
|
||||
if r:
|
||||
#self.myform['freq'].set_value(target_freq) # update displayed va
|
||||
#if self.show_debug_info:
|
||||
|
@ -628,8 +641,10 @@ if __name__ == "__main__":
|
|||
msg = tb.output_q.delete_head()
|
||||
if tb.process_qmsg(msg):
|
||||
break
|
||||
except KeyboardInterrupt:
|
||||
print 'keyboard interrupt'
|
||||
except:
|
||||
sys.stderr.write('main: exception occurred\n')
|
||||
sys.stderr.write('main: exception:\n%s\n' % traceback.format_exc())
|
||||
tb.terminal.end_curses()
|
||||
tb.stop()
|
||||
if tb.kill_sink:
|
||||
tb.kill_sink.kill()
|
||||
|
|
|
@ -27,6 +27,7 @@ import curses.textpad
|
|||
import time
|
||||
import json
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
from gnuradio import gr
|
||||
|
||||
|
@ -39,7 +40,6 @@ class curses_terminal(threading.Thread):
|
|||
self.keep_running = True
|
||||
self.last_update = 0
|
||||
self.auto_update = True
|
||||
self.setup_curses()
|
||||
self.current_nac = None
|
||||
self.start()
|
||||
|
||||
|
@ -58,6 +58,12 @@ class curses_terminal(threading.Thread):
|
|||
|
||||
self.textpad = curses.textpad.Textbox(self.text_win)
|
||||
|
||||
def end_curses(self):
|
||||
try:
|
||||
curses.endwin()
|
||||
except:
|
||||
pass
|
||||
|
||||
def do_auto_update(self):
|
||||
UPDATE_INTERVAL = 1 # sec.
|
||||
if not self.auto_update:
|
||||
|
@ -104,6 +110,8 @@ class curses_terminal(threading.Thread):
|
|||
if freq:
|
||||
msg = gr.message().make_from_string('set_freq', -2, freq, 0)
|
||||
self.output_q.insert_tail(msg)
|
||||
elif c == ord('x'):
|
||||
assert 1 == 0
|
||||
return False
|
||||
|
||||
def process_json(self, js):
|
||||
|
@ -163,11 +171,17 @@ class curses_terminal(threading.Thread):
|
|||
return False
|
||||
|
||||
def run(self):
|
||||
while(self.keep_running):
|
||||
if self.process_terminal_events():
|
||||
break
|
||||
if self.process_q_events():
|
||||
break
|
||||
curses.endwin()
|
||||
try:
|
||||
self.setup_curses()
|
||||
while(self.keep_running):
|
||||
if self.process_terminal_events():
|
||||
break
|
||||
if self.process_q_events():
|
||||
break
|
||||
except:
|
||||
sys.stderr.write('terminal: exception occurred\n')
|
||||
sys.stderr.write('terminal: exception:\n%s\n' % traceback.format_exc())
|
||||
finally:
|
||||
self.end_curses()
|
||||
msg = gr.message().make_from_string('quit', -2, 0, 0)
|
||||
self.output_q.insert_tail(msg)
|
||||
|
|
Loading…
Reference in New Issue