概要
pythonでgnuradioやってみた。
練習問題、やってみた。
練習問題
rtl-sdrで83.4MHzのFMラジオを受信せよ。
方針
- FM DEMOD使う。
サンプルコード
from PyQt5 import Qt
from gnuradio import qtgui
from gnuradio import analog
from gnuradio import audio
from gnuradio import filter
from gnuradio.filter import firdes
from gnuradio import gr
from gnuradio.fft import window
import sys
import signal
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
from gnuradio import soapy
class top_block(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Top Block", catch_exceptions=True)
Qt.QWidget.__init__(self)
self.setWindowTitle("Top Block")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except BaseException as exc:
print(f"Qt GUI: Could not set Icon: {str(exc)}", file=sys.stderr)
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)
self.settings = Qt.QSettings("GNU Radio", "top_block")
try:
geometry = self.settings.value("geometry")
if geometry:
self.restoreGeometry(geometry)
except BaseException as exc:
print(f"Qt GUI: Could not restore geometry: {str(exc)}", file=sys.stderr)
self.samp_rate = samp_rate = 1024000
self.audio_sample_rate = audio_sample_rate = 48000
self.soapy_rtlsdr_source_0 = None
dev = 'driver=rtlsdr'
stream_args = 'bufflen=16384'
tune_args = ['']
settings = ['']
def _set_soapy_rtlsdr_source_0_gain_mode(channel, agc):
self.soapy_rtlsdr_source_0.set_gain_mode(channel, agc)
if not agc:
self.soapy_rtlsdr_source_0.set_gain(channel, self._soapy_rtlsdr_source_0_gain_value)
self.set_soapy_rtlsdr_source_0_gain_mode = _set_soapy_rtlsdr_source_0_gain_mode
def _set_soapy_rtlsdr_source_0_gain(channel, name, gain):
self._soapy_rtlsdr_source_0_gain_value = gain
if not self.soapy_rtlsdr_source_0.get_gain_mode(channel):
self.soapy_rtlsdr_source_0.set_gain(channel, gain)
self.set_soapy_rtlsdr_source_0_gain = _set_soapy_rtlsdr_source_0_gain
def _set_soapy_rtlsdr_source_0_bias(bias):
if 'biastee' in self._soapy_rtlsdr_source_0_setting_keys:
self.soapy_rtlsdr_source_0.write_setting('biastee', bias)
self.set_soapy_rtlsdr_source_0_bias = _set_soapy_rtlsdr_source_0_bias
self.soapy_rtlsdr_source_0 = soapy.source(dev, "fc32", 1, '', stream_args, tune_args, settings)
self._soapy_rtlsdr_source_0_setting_keys = [a.key for a in self.soapy_rtlsdr_source_0.get_setting_info()]
self.soapy_rtlsdr_source_0.set_sample_rate(0, samp_rate)
self.soapy_rtlsdr_source_0.set_frequency(0, 83400000)
self.soapy_rtlsdr_source_0.set_frequency_correction(0, 0)
self.set_soapy_rtlsdr_source_0_bias(bool(False))
self._soapy_rtlsdr_source_0_gain_value = 20
self.set_soapy_rtlsdr_source_0_gain_mode(0, bool(False))
self.set_soapy_rtlsdr_source_0_gain(0, 'TUNER', 20)
self.rational_resampler_xxx_0_0 = filter.rational_resampler_fff(interpolation = 3, decimation = 64, taps = [], fractional_bw = 0)
self.low_pass_filter_0 = filter.fir_filter_ccf(1, firdes.low_pass(1, samp_rate, 80000, 10000, window.WIN_HAMMING, 6.76))
self.audio_sink_1 = audio.sink(audio_sample_rate, '', True)
self.analog_fm_demod_cf_0 = analog.fm_demod_cf(channel_rate = samp_rate, audio_decim = 1, deviation = 75000, audio_pass = 15000, audio_stop = 18000, gain = 1, tau = (50e-6), )
self.connect((self.analog_fm_demod_cf_0, 0), (self.rational_resampler_xxx_0_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.analog_fm_demod_cf_0, 0))
self.connect((self.rational_resampler_xxx_0_0, 0), (self.audio_sink_1, 0))
self.connect((self.soapy_rtlsdr_source_0, 0), (self.low_pass_filter_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "top_block")
self.settings.setValue("geometry", self.saveGeometry())
self.stop()
self.wait()
event.accept()
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(1, self.samp_rate, 80000, 10000, window.WIN_HAMMING, 6.76))
self.soapy_rtlsdr_source_0.set_sample_rate(0, self.samp_rate)
def get_audio_sample_rate(self):
return self.audio_sample_rate
def set_audio_sample_rate(self, audio_sample_rate):
self.audio_sample_rate = audio_sample_rate
def main(top_block_cls = top_block, options = None):
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def sig_handler(sig = None, frame = None):
tb.stop()
tb.wait()
Qt.QApplication.quit()
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
timer = Qt.QTimer()
timer.start(500)
timer.timeout.connect(lambda: None)
qapp.exec_()
if __name__ == '__main__':
main()
以上。