op25/op25/gr-op25_repeater/apps/gr_gnuplot.py

216 lines
5.7 KiB
Python
Raw Normal View History

2017-04-29 19:57:35 +00:00
#!/usr/bin/env python
# Copyright 2011, 2012, 2013, 2014, 2015 Max H. Parke KA1RBI
#
# This file is part of OP25
#
# OP25 is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# OP25 is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OP25; see the file COPYING. If not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Boston, MA
# 02110-1301, USA.
import sys
import subprocess
from gnuradio import gr, gru, eng_notation
from gnuradio import blocks, audio
from gnuradio.eng_option import eng_option
import numpy as np
from gnuradio import gr
_def_debug = 0
_def_sps = 10
GNUPLOT = '/usr/bin/gnuplot'
class wrap_gp(object):
def __init__(self, sps=_def_sps):
self.sps = sps
2017-05-10 13:45:34 +00:00
self.center_freq = None
self.width = None
self.buf = []
2017-04-29 19:57:35 +00:00
self.attach_gp()
def attach_gp(self):
args = (GNUPLOT, '-noraise')
exe = GNUPLOT
self.gp = subprocess.Popen(args, executable=exe, stdin=subprocess.PIPE)
def kill(self):
self.gp.kill()
self.gp.wait()
def plot(self, buf, bufsz, mode='eye'):
BUFSZ = bufsz
consumed = min(len(buf), BUFSZ-len(self.buf))
if len(self.buf) < BUFSZ:
self.buf.extend(buf[:consumed])
if len(self.buf) < BUFSZ:
return consumed
plots = []
s = ''
while(len(self.buf)):
if mode == 'eye':
if len(self.buf) < self.sps:
break
for i in range(self.sps):
s += '%f\n' % self.buf[i]
s += 'e\n'
self.buf=self.buf[self.sps:]
plots.append('"-" with lines')
elif mode == 'constellation':
for b in self.buf:
s += '%f\t%f\n' % (b.real, b.imag)
s += 'e\n'
self.buf = []
plots.append('"-" with points')
elif mode == 'symbol':
for b in self.buf:
s += '%f\n' % (b)
s += 'e\n'
self.buf = []
plots.append('"-" with dots')
elif mode == 'fft':
2017-05-10 13:45:34 +00:00
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])))
2017-04-29 19:57:35 +00:00
s += 'e\n'
self.buf = []
plots.append('"-" with lines')
self.buf = []
h= 'set terminal x11 noraise\n'
2017-05-10 13:45:34 +00:00
background = 'set object 1 circle from screen 0,0 to screen 1,1 fillcolor rgb"black"\n'
2017-04-29 19:57:35 +00:00
h+= 'set key off\n'
if mode == 'constellation':
2017-05-10 13:45:34 +00:00
h += background
h+= 'set size square\n'
2017-04-29 19:57:35 +00:00
h+= 'set xrange [-1:1]\n'
h+= 'set yrange [-1:1]\n'
elif mode == 'eye':
2017-05-10 13:45:34 +00:00
h += background
2017-04-29 19:57:35 +00:00
h+= 'set yrange [-4:4]\n'
elif mode == 'symbol':
2017-05-10 13:45:34 +00:00
h += background
2017-04-29 19:57:35 +00:00
h+= 'set yrange [-4:4]\n'
2017-05-10 13:45:34 +00:00
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)
2017-04-29 19:57:35 +00:00
dat = '%splot %s\n%s' % (h, ','.join(plots), s)
self.gp.stdin.write(dat)
return consumed
2017-05-10 13:45:34 +00:00
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
2017-04-29 19:57:35 +00:00
class eye_sink_f(gr.sync_block):
"""
"""
def __init__(self, debug = _def_debug, sps = _def_sps):
gr.sync_block.__init__(self,
name="eye_sink_f",
in_sig=[np.float32],
out_sig=None)
self.debug = debug
self.sps = sps
self.gnuplot = wrap_gp(sps=self.sps)
def work(self, input_items, output_items):
in0 = input_items[0]
consumed = self.gnuplot.plot(in0, 100 * self.sps, mode='eye')
return consumed ### len(input_items[0])
def kill(self):
self.gnuplot.kill()
class constellation_sink_c(gr.sync_block):
"""
"""
def __init__(self, debug = _def_debug):
gr.sync_block.__init__(self,
name="constellation_sink_c",
in_sig=[np.complex64],
out_sig=None)
self.debug = debug
self.gnuplot = wrap_gp()
def work(self, input_items, output_items):
in0 = input_items[0]
self.gnuplot.plot(in0, 1000, mode='constellation')
return len(input_items[0])
def kill(self):
self.gnuplot.kill()
class fft_sink_c(gr.sync_block):
"""
"""
def __init__(self, debug = _def_debug):
gr.sync_block.__init__(self,
name="fft_sink_c",
in_sig=[np.complex64],
out_sig=None)
self.debug = debug
self.gnuplot = wrap_gp()
2017-05-10 13:45:34 +00:00
self.skip = 0
2017-04-29 19:57:35 +00:00
def work(self, input_items, output_items):
2017-05-10 13:45:34 +00:00
self.skip += 1
if self.skip == 50:
self.skip = 0
in0 = input_items[0]
self.gnuplot.plot(in0, 512, mode='fft')
2017-04-29 19:57:35 +00:00
return len(input_items[0])
def kill(self):
self.gnuplot.kill()
2017-05-10 13:45:34 +00:00
def set_center_freq(self, f):
self.gnuplot.set_center_freq(f)
def set_width(self, w):
self.gnuplot.set_width(w)
2017-04-29 19:57:35 +00:00
class symbol_sink_f(gr.sync_block):
"""
"""
def __init__(self, debug = _def_debug):
gr.sync_block.__init__(self,
name="symbol_sink_f",
in_sig=[np.float32],
out_sig=None)
self.debug = debug
self.gnuplot = wrap_gp()
def work(self, input_items, output_items):
in0 = input_items[0]
self.gnuplot.plot(in0, 2400, mode='symbol')
return len(input_items[0])
def kill(self):
self.gnuplot.kill()