GRC 產生的 Python 檔
2024年4月25日大约 4 分鐘
一個簡單的 GNU Radio 系統架構
由 GRC 產生出來的 Python 檔
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: Not titled yet
# Author: jyw
# GNU Radio version: 3.10.1.1
from packaging.version import Version as StrictVersion
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print("Warning: failed to XInitThreads()")
from PyQt5 import Qt
from gnuradio import qtgui
from gnuradio.filter import firdes
import sip
from gnuradio import analog
from gnuradio import blocks
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 qtgui
class basic(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Not titled yet", catch_exceptions=True)
Qt.QWidget.__init__(self)
self.setWindowTitle("Not titled yet")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
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", "basic")
try:
if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
self.restoreGeometry(self.settings.value("geometry").toByteArray())
else:
self.restoreGeometry(self.settings.value("geometry"))
except:
pass
##################################################
# Variables
##################################################
self.samp_rate = samp_rate = 32000
##################################################
# Blocks
##################################################
self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
1024, #size
window.WIN_BLACKMAN_hARRIS, #wintype
0, #fc
samp_rate, #bw
"", #name
1,
None # parent
)
self.qtgui_freq_sink_x_0.set_update_time(0.10)
self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
self.qtgui_freq_sink_x_0.enable_autoscale(False)
self.qtgui_freq_sink_x_0.enable_grid(False)
self.qtgui_freq_sink_x_0.set_fft_average(1.0)
self.qtgui_freq_sink_x_0.enable_axis_labels(True)
self.qtgui_freq_sink_x_0.enable_control_panel(False)
self.qtgui_freq_sink_x_0.set_fft_window_normalized(False)
labels = ['', '', '', '', '',
'', '', '', '', '']
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ["blue", "red", "green", "black", "cyan",
"magenta", "yellow", "dark red", "dark green", "dark blue"]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in range(1):
if len(labels[i]) == 0:
self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.qwidget(), Qt.QWidget)
self.top_layout.addWidget(self._qtgui_freq_sink_x_0_win)
self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
self.analog_sig_source_x_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, 1000, 1, 0, 0)
##################################################
# Connections
##################################################
self.connect((self.analog_sig_source_x_0, 0), (self.blocks_throttle_0, 0))
self.connect((self.blocks_throttle_0, 0), (self.qtgui_freq_sink_x_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "basic")
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.analog_sig_source_x_0.set_sampling_freq(self.samp_rate)
self.blocks_throttle_0.set_sample_rate(self.samp_rate)
self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate)
def main(top_block_cls=basic, options=None):
if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
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()
程式架構
上面的程式是使用 GNU Radio 和 PyQt5 所建構出來的 Python 應用程式,它主要用來創建一個簡單的系統,能夠生成弦波訊號並分析其訊號頻率。下表是主要區塊和相關的說明:
區塊 | 說明 |
---|---|
引入依賴套件 | 引入需要的套件,如PyQt5 用於GUI,gnuradio 用於信號處理 |
環境設置 | 檢查和設置運行環境,檢查是否需要載入 X11 環境的程式庫;設定系統訊號的處理方法 |
類別定義 | 定義basic 類別,這是系統的主類別,整合了GUI界面與訊號處理流程 |
訊號處理模組 | 包括訊號源、節流塊和頻率顯示器 |
訊號連接 | 連接訊號源、節流塊和頻率顯示器以形成完整的訊號處理流程 |
GUI 設定 | 設置窗口屬性、佈局和訊號處理模組的參數 |
主函數 | 初始化基礎類別實例,啓動訊號處理和 GUI 界面 |
執行 | 程式執行入口,確保程式以主模式運行 |
詳細説明
引入依賴套件:文件開始時引入了多個套件,例如
PyQt5
用於GUI,gnuradio
相關模組用於訊號處理。環境設置:
- 檢查運行平台是否為Linux,如果是的話則調用
libX11.so
程式庫,確保 X11 的圖形界面可以正確運行。 - 設置系統訊號的處理,當接收到中斷或結束訊號時關閉程式。
- 檢查運行平台是否為Linux,如果是的話則調用
類別定義:
- 定義一個名為
basic
的類別,繼承自gr.top_block
和Qt.QWidget
。這個類別用來設置應用程式的 GUI 界面和訊號處理流程。 - 在類別的初始化方法中,設置視窗屬性、佈局以及訊號處理模組,包括訊號源
analog_sig_source_x_0
、節流塊blocks_throttle_0
,以及頻率顯示器qtgui_freq_sink_x_0
。
- 定義一個名為
訊號處理模組:
analog_sig_source_x_0
: 生成固定頻率的餘弦波訊號源。blocks_throttle_0
: 用於控制訊號流的速率,防止過快消耗CPU資源。qtgui_freq_sink_x_0
: 用於顯示訊號的頻率分佈。
訊號連接:
- 將訊號源連接到節流塊,然後輸出到頻率顯示器,以顯示訊號源所發出的訊號頻率分佈。
GUI 設定:
- 設置訊號源的參數,例如取樣速度和頻率。
- 管理應用視窗的佈置和用户界面設置。
主函數:
- 檢查Qt版本,設置圖形系統。
- 創建
basic
類別的實例,設定系統訊號處理,顯示應用程式。 - 處理系統訊號和定時器事件,以正確關閉和啓動程式。
執行:
- 程式底部的執行入口用來確保當程式作為主程式運行時能執行 main 函數。
練習 1
試著在 GNU Radio 的 Python 環境中執行產生的 Python 程式檔,應該會得到與 GRC 中相同的運行結果。