Code:

#!/usr/bin/env python ################################################## # Gnuradio Python Flow Graph # Title: Sradio # Author: Keith Nuesslein # Description: Sradio 1.01 FM radio with seek tuning # Generated: Fri Sep 7 10:17:42 2012 ################################################## from PyQt4 import Qt from gnuradio import audio from gnuradio import blks2 from gnuradio import eng_notation from gnuradio import gr from gnuradio.eng_option import eng_option from gnuradio.gr import firdes from optparse import OptionParser import PyQt4.Qwt5 as Qwt import baz import sys import threading import time class Sradio(gr.top_block, Qt.QWidget): def __init__(self, squelchThreshold=-60, deemphasis=75e-6, defaultStation=96.7, lpfCutoff=100000, magAlpha=0.001, sdrFreqCorr=82, srate=1.920e6, rfGain=1, epsilon=.01, scanThreshold=0.3): gr.top_block.__init__(self, "Sradio") Qt.QWidget.__init__(self) self.setWindowTitle("Sradio") self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) ################################################## # Parameters ################################################## self.squelchThreshold = squelchThreshold self.deemphasis = deemphasis self.defaultStation = defaultStation self.lpfCutoff = lpfCutoff self.magAlpha = magAlpha self.sdrFreqCorr = sdrFreqCorr self.srate = srate self.rfGain = rfGain self.epsilon = epsilon self.scanThreshold = scanThreshold ################################################## # Variables ################################################## self.probe = probe = 0 self.f = f = defaultStation self.vol = vol = 1 self.variable_qtgui_label_0 = variable_qtgui_label_0 = "%7.3f %23s%6.1f Mhz" % (probe," ",f) self.variable_qtgui_chooser_0 = variable_qtgui_chooser_0 = 1 self.samp_rate = samp_rate = srate self.dec = dec = 8 ################################################## # Blocks ################################################## self._vol_layout = Qt.QVBoxLayout() self._vol_label = Qt.QLabel("Volume") self._vol_slider = Qwt.QwtSlider(None, Qt.Qt.Horizontal, Qwt.QwtSlider.BottomScale, Qwt.QwtSlider.BgSlot) self._vol_slider.setRange(0, 10, .5) self._vol_slider.setValue(self.vol) self._vol_slider.setMinimumWidth(200) self._vol_slider.valueChanged.connect(self.set_vol) self._vol_label.setAlignment(Qt.Qt.AlignBottom | Qt.Qt.AlignHCenter) self._vol_layout.addWidget(self._vol_label) self._vol_layout.addWidget(self._vol_slider) self.top_grid_layout.addLayout(self._vol_layout, 2,10) self._f_layout = Qt.QVBoxLayout() self._f_label = Qt.QLabel("FM Tuner") self._f_slider = Qwt.QwtSlider(None, Qt.Qt.Horizontal, Qwt.QwtSlider.BottomScale, Qwt.QwtSlider.BgSlot) self._f_slider.setRange(87.5, 108.1, .2) self._f_slider.setValue(self.f) self._f_slider.setMinimumWidth(200) self._f_slider.valueChanged.connect(self.set_f) self._f_label.setAlignment(Qt.Qt.AlignBottom | Qt.Qt.AlignHCenter) self._f_layout.addWidget(self._f_label) self._f_layout.addWidget(self._f_slider) self.top_grid_layout.addLayout(self._f_layout, 0,1,1,10) self.avgmag2 = gr.probe_avg_mag_sqrd_c(squelchThreshold, magAlpha) self._variable_qtgui_label_0_tool_bar = Qt.QToolBar(self) self._variable_qtgui_label_0_tool_bar.addWidget(Qt.QLabel("Signal"+": ")) self._variable_qtgui_label_0_label = Qt.QLabel(str(self.variable_qtgui_label_0)) self._variable_qtgui_label_0_tool_bar.addWidget(self._variable_qtgui_label_0_label) self.top_grid_layout.addWidget(self._variable_qtgui_label_0_tool_bar, 3,1,1,10) self._variable_qtgui_chooser_0_options = (0, 1, 2, ) self._variable_qtgui_chooser_0_labels = ("DOWN", "STOP", "UP", ) self._variable_qtgui_chooser_0_group_box = Qt.QGroupBox("Seekmode") self._variable_qtgui_chooser_0_box = Qt.QHBoxLayout() self._variable_qtgui_chooser_0_button_group = Qt.QButtonGroup() self._variable_qtgui_chooser_0_group_box.setLayout(self._variable_qtgui_chooser_0_box) for i, label in enumerate(self._variable_qtgui_chooser_0_labels): radio_button = Qt.QRadioButton(label) self._variable_qtgui_chooser_0_box.addWidget(radio_button) self._variable_qtgui_chooser_0_button_group.addButton(radio_button, i) self._variable_qtgui_chooser_0_callback = lambda i: self._variable_qtgui_chooser_0_button_group.button(self._variable_qtgui_chooser_0_options.index(i)).setChecked(True) self._variable_qtgui_chooser_0_callback(self.variable_qtgui_chooser_0) self._variable_qtgui_chooser_0_button_group.buttonClicked[int].connect( lambda i: self.set_variable_qtgui_chooser_0(self._variable_qtgui_chooser_0_options[i])) self.top_grid_layout.addWidget(self._variable_qtgui_chooser_0_group_box, 2,1) self.rtl2832_source_0 = baz.rtl_source_c(defer_creation=True, output_size=gr.sizeof_gr_complex) self.rtl2832_source_0.set_verbose(True) self.rtl2832_source_0.set_vid(0x0) self.rtl2832_source_0.set_pid(0x0) self.rtl2832_source_0.set_tuner_name("e4k") self.rtl2832_source_0.set_default_timeout(0) self.rtl2832_source_0.set_use_buffer(True) self.rtl2832_source_0.set_fir_coefficients(([])) self.rtl2832_source_0.set_read_length(0) if self.rtl2832_source_0.create() == False: raise Exception("Failed to create RTL2832 Source: rtl2832_source_0") self.rtl2832_source_0.set_sample_rate(samp_rate) self.rtl2832_source_0.set_frequency(f*1e6) self.rtl2832_source_0.set_auto_gain_mode(False) self.rtl2832_source_0.set_relative_gain(True) self.rtl2832_source_0.set_gain(rfGain) def scan(scanmode): if scanmode == 1: return self.set_squelchThreshold(10) # mute while scanning step = 0.2 if scanmode == 2 else -0.2 f = self.f + step if f > 108: f = 87.5 if f < 87.5: f = 108.1 # must be odd freq self.set_f(f) # find greatest level in scanmode direction (assumes positive slope) def scantune(scanmode,val): print "

scantune %4.1f %f" % (self.f,val) self.set_variable_qtgui_chooser_0(1) step = 0.2 if scanmode == 2 else -0.2 while True: f=self.f + step self.set_f(f) time.sleep(0.5) newval = self.avgmag2.level() print "%4.2f %f %4.2f %f" % (f-step,val,f,newval) if (newval <= val + self.epsilon): break val = newval f=self.f - step self.set_f(f) def _probe_probe(): while True: val = self.avgmag2.level() if (val > scanThreshold) and (scanmode <> 1) and (oldval < val): scantune(scanmode,val) scanmode = 1 else: self.set_squelchThreshold(squelchThreshold) # unmute scanmode = self.get_variable_qtgui_chooser_0() scan(scanmode) oldval = val try: self.set_probe(val) except AttributeError, e: pass time.sleep(1.0/(5)) _probe_thread = threading.Thread(target=_probe_probe) _probe_thread.daemon = True self.low_pass_filter_1 = gr.fir_filter_fff(5, firdes.low_pass( vol*50, samp_rate/dec, 15000, 1000, firdes.WIN_HAMMING, 6.76)) self.low_pass_filter_0 = gr.fir_filter_ccf(dec, firdes.low_pass( 4, samp_rate, lpfCutoff, 8000, firdes.WIN_HAMMING, 6.76)) self.gr_simple_squelch_cc_0 = gr.simple_squelch_cc(squelchThreshold, magAlpha) self.blks2_wfm_rcv_0 = blks2.wfm_rcv( quad_rate=samp_rate/dec, audio_decimation=1, ) self.blks2_fm_deemph_0 = blks2.fm_deemph(fs=samp_rate/dec, tau=deemphasis) self.audio_sink_0 = audio.sink(48000, "pulse", True) ################################################## # Connections ################################################## self.connect((self.low_pass_filter_0, 0), (self.avgmag2, 0)) self.connect((self.gr_simple_squelch_cc_0, 0), (self.blks2_wfm_rcv_0, 0)) self.connect((self.blks2_wfm_rcv_0, 0), (self.blks2_fm_deemph_0, 0)) self.connect((self.low_pass_filter_0, 0), (self.gr_simple_squelch_cc_0, 0)) self.connect((self.low_pass_filter_1, 0), (self.audio_sink_0, 0)) self.connect((self.blks2_fm_deemph_0, 0), (self.low_pass_filter_1, 0)) self.connect((self.rtl2832_source_0, 0), (self.low_pass_filter_0, 0)) _probe_thread.start() def get_squelchThreshold(self): return self.squelchThreshold def set_squelchThreshold(self, squelchThreshold): self.squelchThreshold = squelchThreshold self.avgmag2.set_threshold(self.squelchThreshold) self.gr_simple_squelch_cc_0.set_threshold(self.squelchThreshold) def get_deemphasis(self): return self.deemphasis def set_deemphasis(self, deemphasis): self.deemphasis = deemphasis def get_defaultStation(self): return self.defaultStation def set_defaultStation(self, defaultStation): self.defaultStation = defaultStation self.set_f(self.defaultStation) def get_lpfCutoff(self): return self.lpfCutoff def set_lpfCutoff(self, lpfCutoff): self.lpfCutoff = lpfCutoff self.low_pass_filter_0.set_taps(firdes.low_pass(4, self.samp_rate, self.lpfCutoff, 8000, firdes.WIN_HAMMING, 6.76)) def get_magAlpha(self): return self.magAlpha def set_magAlpha(self, magAlpha): self.magAlpha = magAlpha self.avgmag2.set_alpha(self.magAlpha) self.gr_simple_squelch_cc_0.set_alpha(self.magAlpha) def get_sdrFreqCorr(self): return self.sdrFreqCorr def set_sdrFreqCorr(self, sdrFreqCorr): self.sdrFreqCorr = sdrFreqCorr def get_srate(self): return self.srate def set_srate(self, srate): self.srate = srate self.set_samp_rate(self.srate) def get_rfGain(self): return self.rfGain def set_rfGain(self, rfGain): self.rfGain = rfGain self.rtl2832_source_0.set_gain(self.rfGain) def get_epsilon(self): return self.epsilon def set_epsilon(self, epsilon): self.epsilon = epsilon def get_scanThreshold(self): return self.scanThreshold def set_scanThreshold(self, scanThreshold): self.scanThreshold = scanThreshold def get_probe(self): return self.probe def set_probe(self, probe): self.probe = probe self.set_variable_qtgui_label_0("%7.3f %23s%6.1f Mhz" % (self.probe," ",self.f) ) def get_f(self): return self.f def set_f(self, f): self.f = f self.set_variable_qtgui_label_0("%7.3f %23s%6.1f Mhz" % (self.probe," ",self.f) ) self._f_slider.setValue(self.f) self.rtl2832_source_0.set_frequency(self.f*1e6) def get_vol(self): return self.vol def set_vol(self, vol): self.vol = vol self._vol_slider.setValue(self.vol) self.low_pass_filter_1.set_taps(firdes.low_pass(self.vol*50, self.samp_rate/self.dec, 15000, 1000, firdes.WIN_HAMMING, 6.76)) def get_variable_qtgui_label_0(self): return self.variable_qtgui_label_0 def set_variable_qtgui_label_0(self, variable_qtgui_label_0): self.variable_qtgui_label_0 = variable_qtgui_label_0 self._variable_qtgui_label_0_label.setText(str(self.variable_qtgui_label_0)) def get_variable_qtgui_chooser_0(self): return self.variable_qtgui_chooser_0 def set_variable_qtgui_chooser_0(self, variable_qtgui_chooser_0): self.variable_qtgui_chooser_0 = variable_qtgui_chooser_0 self._variable_qtgui_chooser_0_callback(self.variable_qtgui_chooser_0) def get_samp_rate(self): return self.samp_rate def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate self.low_pass_filter_0.set_taps(firdes.low_pass(4, self.samp_rate, self.lpfCutoff, 8000, firdes.WIN_HAMMING, 6.76)) self.low_pass_filter_1.set_taps(firdes.low_pass(self.vol*50, self.samp_rate/self.dec, 15000, 1000, firdes.WIN_HAMMING, 6.76)) self.rtl2832_source_0.set_sample_rate(self.samp_rate) def get_dec(self): return self.dec def set_dec(self, dec): self.dec = dec self.low_pass_filter_1.set_taps(firdes.low_pass(self.vol*50, self.samp_rate/self.dec, 15000, 1000, firdes.WIN_HAMMING, 6.76)) if __name__ == '__main__': parser = OptionParser(option_class=eng_option, usage="%prog: [options]") parser.add_option("-t", "--squelchThreshold", dest="squelchThreshold", type="intx", default=-60, help="Set squelchThreshold [default=%default]") parser.add_option("-e", "--deemphasis", dest="deemphasis", type="eng_float", default=eng_notation.num_to_str(75e-6), help="Set deemphasis [default=%default]") parser.add_option("-d", "--defaultStation", dest="defaultStation", type="eng_float", default=eng_notation.num_to_str(96.7), help="Set (Mhz) [default=%default]") parser.add_option("-l", "--lpfCutoff", dest="lpfCutoff", type="long", default=100000, help="Set rf lowpass filter [default=%default]") parser.add_option("-m", "--magAlpha", dest="magAlpha", type="eng_float", default=eng_notation.num_to_str(0.001), help="Set signal mag alpha [default=%default]") parser.add_option("-c", "--sdrFreqCorr", dest="sdrFreqCorr", type="intx", default=82, help="Set sdrFreqCorr [default=%default]") parser.add_option("-r", "--srate", dest="srate", type="eng_float", default=eng_notation.num_to_str(1.920e6), help="Set srate [default=%default]") parser.add_option("-g", "--rfGain", dest="rfGain", type="eng_float", default=eng_notation.num_to_str(1), help="Set rfGain [default=%default]") parser.add_option("-p", "--epsilon", dest="epsilon", type="eng_float", default=eng_notation.num_to_str(.01), help="Set min diff [default=%default]") parser.add_option("-s", "--scanThreshold", dest="scanThreshold", type="eng_float", default=eng_notation.num_to_str(0.3), help="Set scan signal detect threshold [default=%default]") (options, args) = parser.parse_args() qapp = Qt.QApplication(sys.argv) tb = Sradio(squelchThreshold=options.squelchThreshold, deemphasis=options.deemphasis, defaultStation=options.defaultStation, lpfCutoff=options.lpfCutoff, magAlpha=options.magAlpha, sdrFreqCorr=options.sdrFreqCorr, srate=options.srate, rfGain=options.rfGain, epsilon=options.epsilon, scanThreshold=options.scanThreshold) tb.start() tb.show() qapp.exec_() tb.stop()