summaryrefslogtreecommitdiff
path: root/gr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py
diff options
context:
space:
mode:
Diffstat (limited to 'gr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py')
-rwxr-xr-xgr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py306
1 files changed, 0 insertions, 306 deletions
diff --git a/gr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py b/gr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py
deleted file mode 100755
index 05f047e11..000000000
--- a/gr-msdd6000/src/python-examples/msdd_spectrum_waterfall.py
+++ /dev/null
@@ -1,306 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio 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.
-#
-# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street,
-# Boston, MA 02110-1301, USA.
-#
-
-from gnuradio import gr, gru, eng_notation, optfir, window
-from gnuradio import msdd
-from gnuradio.eng_option import eng_option
-from optparse import OptionParser
-import sys
-import math
-import struct
-from pylab import *
-from numpy import array
-import time
-
-matplotlib.interactive(True)
-matplotlib.use('TkAgg')
-
-class tune(gr.feval_dd):
- """
- This class allows C++ code to callback into python.
- """
- def __init__(self, tb):
- gr.feval_dd.__init__(self)
- self.tb = tb
-
- def eval(self, ignore):
- """
- This method is called from gr.bin_statistics_f when it wants to change
- the center frequency. This method tunes the front end to the new center
- frequency, and returns the new frequency as its result.
- """
- try:
- # We use this try block so that if something goes wrong from here
- # down, at least we'll have a prayer of knowing what went wrong.
- # Without this, you get a very mysterious:
- #
- # terminate called after throwing an instance of 'Swig::DirectorMethodException'
- # Aborted
- #
- # message on stderr. Not exactly helpful ;)
-
- new_freq = self.tb.set_next_freq()
- return new_freq
-
- except Exception, e:
- print "tune: Exception: ", e
-
-
-class parse_msg(object):
- def __init__(self, sample_rate, percent):
- self.axis_font_size = 16
- self.label_font_size = 18
- self.title_font_size = 20
- self.text_size = 22
-
- # Set up figures and subplots
- self.fig = figure(1, facecolor="w", figsize=(12,9))
- self.sp = self.fig.add_subplot(1,1,1)
- self.pl = self.sp.matshow(100*[range(100),])
-
- params = {'xtick.labelsize': self.axis_font_size,
- 'ytick.labelsize': self.axis_font_size}
- rcParams.update(params)
-
- # Throw up some title info
- self.sp.set_title(("FFT"), fontsize=self.title_font_size, fontweight="bold")
- self.sp.set_xlabel("Frequency (Hz)", fontsize=self.label_font_size, fontweight="bold")
- self.sp.set_ylabel("Sample index (should be time)", fontsize=self.label_font_size, fontweight="bold")
-
- self.freqrange = list()
- self.data = list()
- self.data3 = list()
-
- self.index = 0
- self.last_cfreq = 0
-
- # So we know how to splice the data
- self.sample_rate = sample_rate
- self.percent = (1.0-percent)/2.0
-
- def parse(self, msg):
- self.center_freq = msg.arg1() # read the current center frequency
- self.vlen = int(msg.arg2()) # read the length of the data set received
-
- # wait until we wrap around before plotting the entire collected band
- if(self.center_freq < self.last_cfreq):
- #print "Plotting spectrum\n"
-
- # If we have 100 sets, start dropping the oldest
- if(len(self.data3) > 100):
- self.data3.pop(0)
- self.data3.append(self.data)
-
- # add the new data to the plot
- self.pl.set_data(self.data3)
- draw()
-
- # reset lists to collect next round
- self.index = 0
- del self.freqrange
- self.freqrange = list()
- del self.data
- self.data = list()
- #raw_input()
-
- self.last_cfreq = self.center_freq
-
- startind = int(self.percent * self.vlen)
- endind = int((1.0 - self.percent) * self.vlen)
-
- fstep = self.sample_rate / self.vlen
- f = [self.center_freq - self.sample_rate/2.0 + i*fstep for i in range(startind, endind)]
- self.freqrange += f
-
- t = msg.to_string();
-
- d = struct.unpack('%df' % (self.vlen,), t)
-
- self.data += [di for di in d[startind:endind]]
-
-
-class my_top_block(gr.top_block):
- def __init__(self):
- gr.top_block.__init__(self)
-
- # Build an options parser to bring in information from the user on usage
- usage = "usage: %prog [options] host min_freq max_freq"
- parser = OptionParser(option_class=eng_option, usage=usage)
- parser.add_option("-g", "--gain", type="eng_float", default=32,
- help="set gain in dB (default is midpoint)")
- parser.add_option("", "--tune-delay", type="eng_float", default=5e-5, metavar="SECS",
- help="time to delay (in seconds) after changing frequency [default=%default]")
- parser.add_option("", "--dwell-delay", type="eng_float", default=50e-5, metavar="SECS",
- help="time to dwell (in seconds) at a given frequncy [default=%default]")
- parser.add_option("-F", "--fft-size", type="int", default=256,
- help="specify number of FFT bins [default=%default]")
- parser.add_option("-d", "--decim", type="intx", default=16,
- help="set decimation to DECIM [default=%default]")
- parser.add_option("", "--real-time", action="store_true", default=False,
- help="Attempt to enable real-time scheduling")
-
- (options, args) = parser.parse_args()
- if len(args) != 3:
- parser.print_help()
- sys.exit(1)
-
- # get user-provided info on address of MSDD and frequency to sweep
- self.address = args[0]
- self.min_freq = eng_notation.str_to_num(args[1])
- self.max_freq = eng_notation.str_to_num(args[2])
-
- self.decim = options.decim
- self.gain = options.gain
-
- if self.min_freq > self.max_freq:
- self.min_freq, self.max_freq = self.max_freq, self.min_freq # swap them
-
- self.fft_size = options.fft_size
-
- if not options.real_time:
- realtime = False
- else:
- # Attempt to enable realtime scheduling
- r = gr.enable_realtime_scheduling()
- if r == gr.RT_OK:
- realtime = True
- else:
- realtime = False
- print "Note: failed to enable realtime scheduling"
-
- # Sampling rate is hardcoded and cannot be read off device
- adc_rate = 102.4e6
- self.int_rate = adc_rate / self.decim
- print "Sampling rate: ", self.int_rate
-
- # build graph
- self.port = 10001 # required port for UDP packets
-
- # which board, op mode, adx, port
-# self.src = msdd.source_c(0, 1, self.address, self.port) # build source object
-
- self.conv = gr.interleaved_short_to_complex();
-
- self.src = msdd.source_simple(self.address,self.port);
- self.src.set_decim_rate(self.decim) # set decimation rate
-# self.src.set_desired_packet_size(0, 1460) # set packet size to collect
-
- self.set_gain(self.gain) # set receiver's attenuation
- self.set_freq(self.min_freq) # set receiver's rx frequency
-
- # restructure into vector format for FFT input
- s2v = gr.stream_to_vector(gr.sizeof_gr_complex, self.fft_size)
-
- # set up FFT processing block
- mywindow = window.blackmanharris(self.fft_size)
- fft = gr.fft_vcc(self.fft_size, True, mywindow, True)
- power = 0
- for tap in mywindow:
- power += tap*tap
-
- # calculate magnitude squared of output of FFT
- c2mag = gr.complex_to_mag_squared(self.fft_size)
-
- # FIXME the log10 primitive is dog slow
- log = gr.nlog10_ff(10, self.fft_size,
- -20*math.log10(self.fft_size)-10*math.log10(power/self.fft_size))
-
- # Set the freq_step to % of the actual data throughput.
- # This allows us to discard the bins on both ends of the spectrum.
- self.percent = 0.4
-
- # Calculate the frequency steps to use in the collection over the whole bandwidth
- self.freq_step = self.percent * self.int_rate
- self.min_center_freq = self.min_freq + self.freq_step/2
- nsteps = math.ceil((self.max_freq - self.min_freq) / self.freq_step)
- self.max_center_freq = self.min_center_freq + (nsteps * self.freq_step)
-
- self.next_freq = self.min_center_freq
-
- # use these values to set receiver settling time between samples and sampling time
- # the default values provided seem to work well with the MSDD over 100 Mbps ethernet
- tune_delay = max(0, int(round(options.tune_delay * self.int_rate / self.fft_size))) # in fft_frames
- dwell_delay = max(1, int(round(options.dwell_delay * self.int_rate / self.fft_size))) # in fft_frames
-
- # set up message callback routine to get data from bin_statistics_f block
- self.msgq = gr.msg_queue(16)
- self._tune_callback = tune(self) # hang on to this to keep it from being GC'd
-
- # FIXME this block doesn't like to work with negatives because of the "d_max[i]=0" on line
- # 151 of gr_bin_statistics_f.cc file. Set this to -10000 or something to get it to work.
- stats = gr.bin_statistics_f(self.fft_size, self.msgq,
- self._tune_callback, tune_delay, dwell_delay)
-
- # FIXME there's a concern over the speed of the log calculation
- # We can probably calculate the log inside the stats block
- self.connect(self.src, self.conv, s2v, fft, c2mag, log, stats)
-
-
- def set_next_freq(self):
- ''' Find and set the next frequency of the reciver. After going past the maximum frequency,
- the frequency is wrapped around to the start again'''
- target_freq = self.next_freq
- self.next_freq = self.next_freq + self.freq_step
- if self.next_freq >= self.max_center_freq:
- self.next_freq = self.min_center_freq
-
- if not self.set_freq(target_freq):
- print "Failed to set frequency to", target_freq
-
- return target_freq
-
-
- def set_freq(self, target_freq):
- """
- Set the center frequency we're interested in.
-
- @param target_freq: frequency in Hz
- @rypte: bool
-
- """
- return self.src.set_rx_freq(0, target_freq)
-
-
- def set_gain(self, gain):
- self.src.set_pga(0, gain)
-
-
-def main_loop(tb):
- # Set up parser to get data from stats block and display them.
- msgparser = parse_msg(tb.int_rate, tb.percent)
-
- while 1:
- # Get the next message sent from the C++ code (blocking call).
- # It contains the center frequency and the mag squared of the fft
- d = tb.msgq.delete_head();
- print d.to_string();
- msgparser.parse(d)
- #print msgparser.center_freq
-
-if __name__ == '__main__':
- tb = my_top_block()
- try:
- tb.start() # start executing flow graph in another thread...
- main_loop(tb)
-
- except KeyboardInterrupt:
- pass