Advertisement
duggabe

FunCube 2 meter NB FM

Apr 15th, 2020
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.14 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. #
  5. # SPDX-License-Identifier: GPL-3.0
  6. #
  7. # GNU Radio Python Flow Graph
  8. # Title: FunCube  2 meter NB FM
  9. # GNU Radio version: 3.8.1.0
  10.  
  11. from distutils.version import StrictVersion
  12.  
  13. if __name__ == '__main__':
  14.     import ctypes
  15.     import sys
  16.     if sys.platform.startswith('linux'):
  17.         try:
  18.             x11 = ctypes.cdll.LoadLibrary('libX11.so')
  19.             x11.XInitThreads()
  20.         except:
  21.             print("Warning: failed to XInitThreads()")
  22.  
  23. from PyQt5 import Qt
  24. from gnuradio import qtgui
  25. from gnuradio.filter import firdes
  26. import sip
  27. from gnuradio import analog
  28. from gnuradio import audio
  29. from gnuradio import blocks
  30. from gnuradio import filter
  31. from gnuradio import gr
  32. import sys
  33. import signal
  34. from argparse import ArgumentParser
  35. from gnuradio.eng_arg import eng_float, intx
  36. from gnuradio import eng_notation
  37. from gnuradio.qtgui import Range, RangeWidget
  38. import fcdproplus
  39. from gnuradio import qtgui
  40.  
  41. class FC_NFM(gr.top_block, Qt.QWidget):
  42.  
  43.     def __init__(self):
  44.         gr.top_block.__init__(self, "FunCube  2 meter NB FM")
  45.         Qt.QWidget.__init__(self)
  46.         self.setWindowTitle("FunCube  2 meter NB FM")
  47.         qtgui.util.check_set_qss()
  48.         try:
  49.             self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
  50.         except:
  51.             pass
  52.         self.top_scroll_layout = Qt.QVBoxLayout()
  53.         self.setLayout(self.top_scroll_layout)
  54.         self.top_scroll = Qt.QScrollArea()
  55.         self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
  56.         self.top_scroll_layout.addWidget(self.top_scroll)
  57.         self.top_scroll.setWidgetResizable(True)
  58.         self.top_widget = Qt.QWidget()
  59.         self.top_scroll.setWidget(self.top_widget)
  60.         self.top_layout = Qt.QVBoxLayout(self.top_widget)
  61.         self.top_grid_layout = Qt.QGridLayout()
  62.         self.top_layout.addLayout(self.top_grid_layout)
  63.  
  64.         self.settings = Qt.QSettings("GNU Radio", "FC_NFM")
  65.  
  66.         try:
  67.             if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
  68.                 self.restoreGeometry(self.settings.value("geometry").toByteArray())
  69.             else:
  70.                 self.restoreGeometry(self.settings.value("geometry"))
  71.         except:
  72.             pass
  73.  
  74.         ##################################################
  75.         # Variables
  76.         ##################################################
  77.         self.volume = volume = 0.50
  78.         self.tuning = tuning = 146.94e6
  79.         self.sq_lvl = sq_lvl = -50
  80.         self.samp_rate = samp_rate = 192000
  81.  
  82.         ##################################################
  83.         # Blocks
  84.         ##################################################
  85.         self._volume_range = Range(0, 1.00, 0.1, 0.50, 200)
  86.         self._volume_win = RangeWidget(self._volume_range, self.set_volume, 'Volume', "dial", float)
  87.         self.top_grid_layout.addWidget(self._volume_win)
  88.         self._tuning_range = Range(144.0e6, 148.0e6, 1.0e3, 146.94e6, 200)
  89.         self._tuning_win = RangeWidget(self._tuning_range, self.set_tuning, 'Tuning', "counter_slider", float)
  90.         self.top_grid_layout.addWidget(self._tuning_win)
  91.         self._sq_lvl_range = Range(-100, 0, 5, -50, 200)
  92.         self._sq_lvl_win = RangeWidget(self._sq_lvl_range, self.set_sq_lvl, 'Squelch', "counter_slider", float)
  93.         self.top_grid_layout.addWidget(self._sq_lvl_win)
  94.         self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c(
  95.             1024, #size
  96.             firdes.WIN_BLACKMAN_hARRIS, #wintype
  97.             0, #fc
  98.             samp_rate, #bw
  99.             "", #name
  100.             1 #number of inputs
  101.         )
  102.         self.qtgui_waterfall_sink_x_0.set_update_time(0.10)
  103.         self.qtgui_waterfall_sink_x_0.enable_grid(False)
  104.         self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)
  105.  
  106.  
  107.  
  108.         labels = ['', '', '', '', '',
  109.                   '', '', '', '', '']
  110.         colors = [0, 0, 0, 0, 0,
  111.                   0, 0, 0, 0, 0]
  112.         alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
  113.                   1.0, 1.0, 1.0, 1.0, 1.0]
  114.  
  115.         for i in range(1):
  116.             if len(labels[i]) == 0:
  117.                 self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
  118.             else:
  119.                 self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
  120.             self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
  121.             self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])
  122.  
  123.         self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)
  124.  
  125.         self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.pyqwidget(), Qt.QWidget)
  126.         self.top_grid_layout.addWidget(self._qtgui_waterfall_sink_x_0_win)
  127.         self.low_pass_filter_0 = filter.fir_filter_ccf(
  128.             1,
  129.             firdes.low_pass(
  130.                 1,
  131.                 samp_rate,
  132.                 6000,
  133.                 2000,
  134.                 firdes.WIN_HAMMING,
  135.                 6.76))
  136.         self.fcdproplus_fcdproplus_0 = fcdproplus.fcdproplus('hw:CARD=V20,DEV=0',1)
  137.         self.fcdproplus_fcdproplus_0.set_lna(1)
  138.         self.fcdproplus_fcdproplus_0.set_mixer_gain(1)
  139.         self.fcdproplus_fcdproplus_0.set_if_gain(20)
  140.         self.fcdproplus_fcdproplus_0.set_freq_corr(-8)
  141.         self.fcdproplus_fcdproplus_0.set_freq(tuning)
  142.         self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_ff(volume)
  143.         self.audio_sink_0 = audio.sink(48000, 'hw:CARD=Device,DEV=0', False)
  144.         self.analog_simple_squelch_cc_0 = analog.simple_squelch_cc(sq_lvl, 1)
  145.         self.analog_nbfm_rx_0 = analog.nbfm_rx(
  146.             audio_rate=48000,
  147.             quad_rate=samp_rate,
  148.             tau=75e-6,
  149.             max_dev=5e3,
  150.           )
  151.  
  152.  
  153.  
  154.         ##################################################
  155.         # Connections
  156.         ##################################################
  157.         self.connect((self.analog_nbfm_rx_0, 0), (self.blocks_multiply_const_vxx_0_0, 0))
  158.         self.connect((self.analog_simple_squelch_cc_0, 0), (self.analog_nbfm_rx_0, 0))
  159.         self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.audio_sink_0, 0))
  160.         self.connect((self.fcdproplus_fcdproplus_0, 0), (self.low_pass_filter_0, 0))
  161.         self.connect((self.fcdproplus_fcdproplus_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
  162.         self.connect((self.low_pass_filter_0, 0), (self.analog_simple_squelch_cc_0, 0))
  163.  
  164.     def closeEvent(self, event):
  165.         self.settings = Qt.QSettings("GNU Radio", "FC_NFM")
  166.         self.settings.setValue("geometry", self.saveGeometry())
  167.         event.accept()
  168.  
  169.     def get_volume(self):
  170.         return self.volume
  171.  
  172.     def set_volume(self, volume):
  173.         self.volume = volume
  174.         self.blocks_multiply_const_vxx_0_0.set_k(self.volume)
  175.  
  176.     def get_tuning(self):
  177.         return self.tuning
  178.  
  179.     def set_tuning(self, tuning):
  180.         self.tuning = tuning
  181.         self.fcdproplus_fcdproplus_0.set_freq(self.tuning)
  182.  
  183.     def get_sq_lvl(self):
  184.         return self.sq_lvl
  185.  
  186.     def set_sq_lvl(self, sq_lvl):
  187.         self.sq_lvl = sq_lvl
  188.         self.analog_simple_squelch_cc_0.set_threshold(self.sq_lvl)
  189.  
  190.     def get_samp_rate(self):
  191.         return self.samp_rate
  192.  
  193.     def set_samp_rate(self, samp_rate):
  194.         self.samp_rate = samp_rate
  195.         self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate, 6000, 2000, firdes.WIN_HAMMING, 6.76))
  196.         self.qtgui_waterfall_sink_x_0.set_frequency_range(0, self.samp_rate)
  197.  
  198.  
  199.  
  200. def main(top_block_cls=FC_NFM, options=None):
  201.  
  202.     if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
  203.         style = gr.prefs().get_string('qtgui', 'style', 'raster')
  204.         Qt.QApplication.setGraphicsSystem(style)
  205.     qapp = Qt.QApplication(sys.argv)
  206.  
  207.     tb = top_block_cls()
  208.     tb.start()
  209.     tb.show()
  210.  
  211.     def sig_handler(sig=None, frame=None):
  212.         Qt.QApplication.quit()
  213.  
  214.     signal.signal(signal.SIGINT, sig_handler)
  215.     signal.signal(signal.SIGTERM, sig_handler)
  216.  
  217.     timer = Qt.QTimer()
  218.     timer.start(500)
  219.     timer.timeout.connect(lambda: None)
  220.  
  221.     def quitting():
  222.         tb.stop()
  223.         tb.wait()
  224.     qapp.aboutToQuit.connect(quitting)
  225.     qapp.exec_()
  226.  
  227.  
  228. if __name__ == '__main__':
  229.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement