fm_radio.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. #
  4. # SPDX-License-Identifier: GPL-3.0
  5. #
  6. # GNU Radio Python Flow Graph
  7. # Title: Not titled yet
  8. # Author: fabianpeter
  9. # GNU Radio version: 3.8.1.0
  10. from distutils.version import StrictVersion
  11. if __name__ == '__main__':
  12. import ctypes
  13. import sys
  14. if sys.platform.startswith('linux'):
  15. try:
  16. x11 = ctypes.cdll.LoadLibrary('libX11.so')
  17. x11.XInitThreads()
  18. except:
  19. print("Warning: failed to XInitThreads()")
  20. from PyQt5 import Qt
  21. from gnuradio import qtgui
  22. from gnuradio.filter import firdes
  23. import sip
  24. from gnuradio import analog
  25. from gnuradio import audio
  26. from gnuradio import blocks
  27. from gnuradio import filter
  28. from gnuradio import gr
  29. import sys
  30. import signal
  31. from argparse import ArgumentParser
  32. from gnuradio.eng_arg import eng_float, intx
  33. from gnuradio import eng_notation
  34. from gnuradio.qtgui import Range, RangeWidget
  35. import osmosdr
  36. import time
  37. from gnuradio import qtgui
  38. class fm_radio(gr.top_block, Qt.QWidget):
  39. def __init__(self):
  40. gr.top_block.__init__(self, "Not titled yet")
  41. Qt.QWidget.__init__(self)
  42. self.setWindowTitle("Not titled yet")
  43. qtgui.util.check_set_qss()
  44. try:
  45. self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
  46. except:
  47. pass
  48. self.top_scroll_layout = Qt.QVBoxLayout()
  49. self.setLayout(self.top_scroll_layout)
  50. self.top_scroll = Qt.QScrollArea()
  51. self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
  52. self.top_scroll_layout.addWidget(self.top_scroll)
  53. self.top_scroll.setWidgetResizable(True)
  54. self.top_widget = Qt.QWidget()
  55. self.top_scroll.setWidget(self.top_widget)
  56. self.top_layout = Qt.QVBoxLayout(self.top_widget)
  57. self.top_grid_layout = Qt.QGridLayout()
  58. self.top_layout.addLayout(self.top_grid_layout)
  59. self.settings = Qt.QSettings("GNU Radio", "fm_radio")
  60. try:
  61. if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
  62. self.restoreGeometry(self.settings.value("geometry").toByteArray())
  63. else:
  64. self.restoreGeometry(self.settings.value("geometry"))
  65. except:
  66. pass
  67. ##################################################
  68. # Variables
  69. ##################################################
  70. self.volume = volume = 0.5
  71. self.samp_rate = samp_rate = 2000000
  72. self.frequency_mhz = frequency_mhz = 98.3
  73. self.down_rate_hertz = down_rate_hertz = 250000
  74. ##################################################
  75. # Blocks
  76. ##################################################
  77. self._volume_range = Range(0, 1, 0.05, 0.5, 200)
  78. self._volume_win = RangeWidget(self._volume_range, self.set_volume, 'Volume', "counter_slider", float)
  79. self.top_grid_layout.addWidget(self._volume_win)
  80. self._frequency_mhz_range = Range(87.5, 108, 0.1, 98.3, 200)
  81. self._frequency_mhz_win = RangeWidget(self._frequency_mhz_range, self.set_frequency_mhz, 'Frequency MHz', "counter_slider", float)
  82. self.top_grid_layout.addWidget(self._frequency_mhz_win)
  83. self.rtlsdr_source_0 = osmosdr.source(
  84. args="numchan=" + str(1) + " " + ""
  85. )
  86. self.rtlsdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t())
  87. self.rtlsdr_source_0.set_sample_rate(samp_rate)
  88. self.rtlsdr_source_0.set_center_freq(frequency_mhz*1e6, 0)
  89. self.rtlsdr_source_0.set_freq_corr(0, 0)
  90. self.rtlsdr_source_0.set_gain(20, 0)
  91. self.rtlsdr_source_0.set_if_gain(20, 0)
  92. self.rtlsdr_source_0.set_bb_gain(20, 0)
  93. self.rtlsdr_source_0.set_antenna('', 0)
  94. self.rtlsdr_source_0.set_bandwidth(0, 0)
  95. self.rational_resampler_xxx_0 = filter.rational_resampler_fff(
  96. interpolation=48000,
  97. decimation=down_rate_hertz,
  98. taps=None,
  99. fractional_bw=None)
  100. self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c(
  101. 1048, #size
  102. firdes.WIN_BLACKMAN_hARRIS, #wintype
  103. frequency_mhz*1e6, #fc
  104. samp_rate, #bw
  105. "", #name
  106. 1 #number of inputs
  107. )
  108. self.qtgui_waterfall_sink_x_0.set_update_time(0.10)
  109. self.qtgui_waterfall_sink_x_0.enable_grid(False)
  110. self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)
  111. labels = ['', '', '', '', '',
  112. '', '', '', '', '']
  113. colors = [0, 0, 0, 0, 0,
  114. 0, 0, 0, 0, 0]
  115. alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
  116. 1.0, 1.0, 1.0, 1.0, 1.0]
  117. for i in range(1):
  118. if len(labels[i]) == 0:
  119. self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
  120. else:
  121. self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
  122. self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
  123. self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])
  124. self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)
  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.qtgui_freq_sink_x_0 = qtgui.freq_sink_f(
  128. 1024, #size
  129. firdes.WIN_BLACKMAN_hARRIS, #wintype
  130. 0, #fc
  131. down_rate_hertz, #bw
  132. "Demod Out", #name
  133. 1
  134. )
  135. self.qtgui_freq_sink_x_0.set_update_time(0.10)
  136. self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
  137. self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
  138. self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
  139. self.qtgui_freq_sink_x_0.enable_autoscale(False)
  140. self.qtgui_freq_sink_x_0.enable_grid(False)
  141. self.qtgui_freq_sink_x_0.set_fft_average(1.0)
  142. self.qtgui_freq_sink_x_0.enable_axis_labels(True)
  143. self.qtgui_freq_sink_x_0.enable_control_panel(False)
  144. self.qtgui_freq_sink_x_0.disable_legend()
  145. self.qtgui_freq_sink_x_0.set_plot_pos_half(not True)
  146. labels = ['', '', '', '', '',
  147. '', '', '', '', '']
  148. widths = [1, 1, 1, 1, 1,
  149. 1, 1, 1, 1, 1]
  150. colors = ["blue", "red", "green", "black", "cyan",
  151. "magenta", "yellow", "dark red", "dark green", "dark blue"]
  152. alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
  153. 1.0, 1.0, 1.0, 1.0, 1.0]
  154. for i in range(1):
  155. if len(labels[i]) == 0:
  156. self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
  157. else:
  158. self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
  159. self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
  160. self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
  161. self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
  162. self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
  163. self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win)
  164. self.low_pass_filter_0 = filter.fir_filter_ccf(
  165. int(samp_rate/down_rate_hertz),
  166. firdes.low_pass(
  167. 2,
  168. samp_rate,
  169. 100000,
  170. 10000,
  171. firdes.WIN_KAISER,
  172. 6.76))
  173. self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(volume)
  174. self.audio_sink_0 = audio.sink(48000, '', True)
  175. self.analog_wfm_rcv_0 = analog.wfm_rcv(
  176. quad_rate=down_rate_hertz,
  177. audio_decimation=1,
  178. )
  179. ##################################################
  180. # Connections
  181. ##################################################
  182. self.connect((self.analog_wfm_rcv_0, 0), (self.qtgui_freq_sink_x_0, 0))
  183. self.connect((self.analog_wfm_rcv_0, 0), (self.rational_resampler_xxx_0, 0))
  184. self.connect((self.blocks_multiply_const_vxx_0, 0), (self.audio_sink_0, 0))
  185. self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_0, 0))
  186. self.connect((self.rational_resampler_xxx_0, 0), (self.blocks_multiply_const_vxx_0, 0))
  187. self.connect((self.rtlsdr_source_0, 0), (self.low_pass_filter_0, 0))
  188. self.connect((self.rtlsdr_source_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
  189. def closeEvent(self, event):
  190. self.settings = Qt.QSettings("GNU Radio", "fm_radio")
  191. self.settings.setValue("geometry", self.saveGeometry())
  192. event.accept()
  193. def get_volume(self):
  194. return self.volume
  195. def set_volume(self, volume):
  196. self.volume = volume
  197. self.blocks_multiply_const_vxx_0.set_k(self.volume)
  198. def get_samp_rate(self):
  199. return self.samp_rate
  200. def set_samp_rate(self, samp_rate):
  201. self.samp_rate = samp_rate
  202. self.low_pass_filter_0.set_taps(firdes.low_pass(2, self.samp_rate, 100000, 10000, firdes.WIN_KAISER, 6.76))
  203. self.qtgui_waterfall_sink_x_0.set_frequency_range(self.frequency_mhz*1e6, self.samp_rate)
  204. self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
  205. def get_frequency_mhz(self):
  206. return self.frequency_mhz
  207. def set_frequency_mhz(self, frequency_mhz):
  208. self.frequency_mhz = frequency_mhz
  209. self.qtgui_waterfall_sink_x_0.set_frequency_range(self.frequency_mhz*1e6, self.samp_rate)
  210. self.rtlsdr_source_0.set_center_freq(self.frequency_mhz*1e6, 0)
  211. def get_down_rate_hertz(self):
  212. return self.down_rate_hertz
  213. def set_down_rate_hertz(self, down_rate_hertz):
  214. self.down_rate_hertz = down_rate_hertz
  215. self.qtgui_freq_sink_x_0.set_frequency_range(0, self.down_rate_hertz)
  216. def main(top_block_cls=fm_radio, options=None):
  217. if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
  218. style = gr.prefs().get_string('qtgui', 'style', 'raster')
  219. Qt.QApplication.setGraphicsSystem(style)
  220. qapp = Qt.QApplication(sys.argv)
  221. tb = top_block_cls()
  222. tb.start()
  223. tb.show()
  224. def sig_handler(sig=None, frame=None):
  225. Qt.QApplication.quit()
  226. signal.signal(signal.SIGINT, sig_handler)
  227. signal.signal(signal.SIGTERM, sig_handler)
  228. timer = Qt.QTimer()
  229. timer.start(500)
  230. timer.timeout.connect(lambda: None)
  231. def quitting():
  232. tb.stop()
  233. tb.wait()
  234. qapp.aboutToQuit.connect(quitting)
  235. qapp.exec_()
  236. if __name__ == '__main__':
  237. main()