fm_radio.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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: FM Radio Receiver
  8. # GNU Radio version: 3.10.5.1
  9. from packaging.version import Version as StrictVersion
  10. if __name__ == '__main__':
  11. import ctypes
  12. import sys
  13. if sys.platform.startswith('linux'):
  14. try:
  15. x11 = ctypes.cdll.LoadLibrary('libX11.so')
  16. x11.XInitThreads()
  17. except:
  18. print("Warning: failed to XInitThreads()")
  19. from PyQt5 import Qt
  20. from gnuradio import qtgui
  21. from gnuradio.filter import firdes
  22. import sip
  23. from gnuradio import analog
  24. from gnuradio import audio
  25. from gnuradio import filter
  26. from gnuradio import gr
  27. from gnuradio.fft import window
  28. import sys
  29. import signal
  30. from argparse import ArgumentParser
  31. from gnuradio.eng_arg import eng_float, intx
  32. from gnuradio import eng_notation
  33. from gnuradio.qtgui import Range, RangeWidget
  34. from PyQt5 import QtCore
  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, "FM Radio Receiver", catch_exceptions=True)
  41. Qt.QWidget.__init__(self)
  42. self.setWindowTitle("FM Radio Receiver")
  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.samp_rate = samp_rate = 2560000
  71. self.frequency_mhz = frequency_mhz = 98.3
  72. self.channel_width_hertz = channel_width_hertz = 250000
  73. self.audio_sample_rate_hertz = audio_sample_rate_hertz = 48000
  74. ##################################################
  75. # Blocks
  76. ##################################################
  77. self._frequency_mhz_range = Range(87.5, 108, 0.1, 98.3, 200)
  78. self._frequency_mhz_win = RangeWidget(self._frequency_mhz_range, self.set_frequency_mhz, "Frequency MHz", "counter_slider", float, QtCore.Qt.Horizontal)
  79. self.top_layout.addWidget(self._frequency_mhz_win)
  80. self.rtlsdr_source_0 = osmosdr.source(
  81. args="numchan=" + str(1) + " " + ""
  82. )
  83. self.rtlsdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t())
  84. self.rtlsdr_source_0.set_sample_rate(samp_rate)
  85. self.rtlsdr_source_0.set_center_freq((frequency_mhz*1e6), 0)
  86. self.rtlsdr_source_0.set_freq_corr(0, 0)
  87. self.rtlsdr_source_0.set_dc_offset_mode(0, 0)
  88. self.rtlsdr_source_0.set_iq_balance_mode(0, 0)
  89. self.rtlsdr_source_0.set_gain_mode(False, 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=audio_sample_rate_hertz,
  97. decimation=channel_width_hertz,
  98. taps=[],
  99. fractional_bw=0)
  100. self.qtgui_waterfall_sink_x_0 = qtgui.waterfall_sink_c(
  101. 1024, #size
  102. window.WIN_BLACKMAN_hARRIS, #wintype
  103. (frequency_mhz*1e6), #fc
  104. samp_rate, #bw
  105. "", #name
  106. 1, #number of inputs
  107. None # parent
  108. )
  109. self.qtgui_waterfall_sink_x_0.set_update_time(0.10)
  110. self.qtgui_waterfall_sink_x_0.enable_grid(False)
  111. self.qtgui_waterfall_sink_x_0.enable_axis_labels(True)
  112. labels = ['', '', '', '', '',
  113. '', '', '', '', '']
  114. colors = [0, 0, 0, 0, 0,
  115. 0, 0, 0, 0, 0]
  116. alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
  117. 1.0, 1.0, 1.0, 1.0, 1.0]
  118. for i in range(1):
  119. if len(labels[i]) == 0:
  120. self.qtgui_waterfall_sink_x_0.set_line_label(i, "Data {0}".format(i))
  121. else:
  122. self.qtgui_waterfall_sink_x_0.set_line_label(i, labels[i])
  123. self.qtgui_waterfall_sink_x_0.set_color_map(i, colors[i])
  124. self.qtgui_waterfall_sink_x_0.set_line_alpha(i, alphas[i])
  125. self.qtgui_waterfall_sink_x_0.set_intensity_range(-140, 10)
  126. self._qtgui_waterfall_sink_x_0_win = sip.wrapinstance(self.qtgui_waterfall_sink_x_0.qwidget(), Qt.QWidget)
  127. self.top_layout.addWidget(self._qtgui_waterfall_sink_x_0_win)
  128. self.qtgui_freq_sink_x_0 = qtgui.freq_sink_f(
  129. 1024, #size
  130. window.WIN_BLACKMAN_hARRIS, #wintype
  131. 0, #fc
  132. channel_width_hertz, #bw
  133. "Demod Out", #name
  134. 1,
  135. None # parent
  136. )
  137. self.qtgui_freq_sink_x_0.set_update_time(0.10)
  138. self.qtgui_freq_sink_x_0.set_y_axis((-140), 10)
  139. self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
  140. self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
  141. self.qtgui_freq_sink_x_0.enable_autoscale(False)
  142. self.qtgui_freq_sink_x_0.enable_grid(False)
  143. self.qtgui_freq_sink_x_0.set_fft_average(1.0)
  144. self.qtgui_freq_sink_x_0.enable_axis_labels(True)
  145. self.qtgui_freq_sink_x_0.enable_control_panel(False)
  146. self.qtgui_freq_sink_x_0.set_fft_window_normalized(False)
  147. self.qtgui_freq_sink_x_0.disable_legend()
  148. self.qtgui_freq_sink_x_0.set_plot_pos_half(not True)
  149. labels = ['', '', '', '', '',
  150. '', '', '', '', '']
  151. widths = [1, 1, 1, 1, 1,
  152. 1, 1, 1, 1, 1]
  153. colors = ["blue", "red", "green", "black", "cyan",
  154. "magenta", "yellow", "dark red", "dark green", "dark blue"]
  155. alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
  156. 1.0, 1.0, 1.0, 1.0, 1.0]
  157. for i in range(1):
  158. if len(labels[i]) == 0:
  159. self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
  160. else:
  161. self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
  162. self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
  163. self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
  164. self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
  165. self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget)
  166. self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win)
  167. self.low_pass_filter_0 = filter.fir_filter_ccf(
  168. (int(samp_rate/channel_width_hertz)),
  169. firdes.low_pass(
  170. 2,
  171. samp_rate,
  172. 100000,
  173. 10000,
  174. window.WIN_KAISER,
  175. 6.76))
  176. self.audio_sink_0 = audio.sink(audio_sample_rate_hertz, '', True)
  177. self.analog_wfm_rcv_0 = analog.wfm_rcv(
  178. quad_rate=channel_width_hertz,
  179. audio_decimation=1,
  180. )
  181. ##################################################
  182. # Connections
  183. ##################################################
  184. self.connect((self.analog_wfm_rcv_0, 0), (self.qtgui_freq_sink_x_0, 0))
  185. self.connect((self.analog_wfm_rcv_0, 0), (self.rational_resampler_xxx_0, 0))
  186. self.connect((self.low_pass_filter_0, 0), (self.analog_wfm_rcv_0, 0))
  187. self.connect((self.rational_resampler_xxx_0, 0), (self.audio_sink_0, 0))
  188. self.connect((self.rtlsdr_source_0, 0), (self.low_pass_filter_0, 0))
  189. self.connect((self.rtlsdr_source_0, 0), (self.qtgui_waterfall_sink_x_0, 0))
  190. def closeEvent(self, event):
  191. self.settings = Qt.QSettings("GNU Radio", "fm_radio")
  192. self.settings.setValue("geometry", self.saveGeometry())
  193. self.stop()
  194. self.wait()
  195. event.accept()
  196. def get_samp_rate(self):
  197. return self.samp_rate
  198. def set_samp_rate(self, samp_rate):
  199. self.samp_rate = samp_rate
  200. self.low_pass_filter_0.set_taps(firdes.low_pass(2, self.samp_rate, 100000, 10000, window.WIN_KAISER, 6.76))
  201. self.qtgui_waterfall_sink_x_0.set_frequency_range((self.frequency_mhz*1e6), self.samp_rate)
  202. self.rtlsdr_source_0.set_sample_rate(self.samp_rate)
  203. def get_frequency_mhz(self):
  204. return self.frequency_mhz
  205. def set_frequency_mhz(self, frequency_mhz):
  206. self.frequency_mhz = frequency_mhz
  207. self.qtgui_waterfall_sink_x_0.set_frequency_range((self.frequency_mhz*1e6), self.samp_rate)
  208. self.rtlsdr_source_0.set_center_freq((self.frequency_mhz*1e6), 0)
  209. def get_channel_width_hertz(self):
  210. return self.channel_width_hertz
  211. def set_channel_width_hertz(self, channel_width_hertz):
  212. self.channel_width_hertz = channel_width_hertz
  213. self.qtgui_freq_sink_x_0.set_frequency_range(0, self.channel_width_hertz)
  214. def get_audio_sample_rate_hertz(self):
  215. return self.audio_sample_rate_hertz
  216. def set_audio_sample_rate_hertz(self, audio_sample_rate_hertz):
  217. self.audio_sample_rate_hertz = audio_sample_rate_hertz
  218. def main(top_block_cls=fm_radio, options=None):
  219. if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
  220. style = gr.prefs().get_string('qtgui', 'style', 'raster')
  221. Qt.QApplication.setGraphicsSystem(style)
  222. qapp = Qt.QApplication(sys.argv)
  223. tb = top_block_cls()
  224. tb.start()
  225. tb.show()
  226. def sig_handler(sig=None, frame=None):
  227. tb.stop()
  228. tb.wait()
  229. Qt.QApplication.quit()
  230. signal.signal(signal.SIGINT, sig_handler)
  231. signal.signal(signal.SIGTERM, sig_handler)
  232. timer = Qt.QTimer()
  233. timer.start(500)
  234. timer.timeout.connect(lambda: None)
  235. qapp.exec_()
  236. if __name__ == '__main__':
  237. main()