usrp_source的接收消息处理机制

usrp_source接收消息处理机制剖析

一、引言

在软件无线电领域中,USRP(Universal Software Radio Peripheral)设备是常用的硬件平台,usrp_source 作为从 USRP 设备获取数据的重要模块,其消息处理机制对于系统的稳定运行和有效控制起着关键作用。本文将结合相关代码,深入剖析 usrp_source 的消息处理机制。

二、代码结构概述

所提供的代码是 usrp_source 实现的一部分,属于 GNU Radio 框架中与 UHD(Universal Hardware Driver)相关的内容。代码定义了 usrp_source 类及其实现类 usrp_source_impl,涵盖了设备参数设置、消息端口管理、命令处理等多个与消息处理相关的功能模块。

三、usrp_source消息处理关键部分

(一)消息端口管理

  1. 消息端口注册
    usrp_source_impl 的构造函数中,通过以下代码注册了一个输出消息端口:
message_port_register_out(ASYNC_MSGS_PORT_KEY);

这表明 usrp_source 模块能够通过 ASYNC_MSGS_PORT_KEY 这个端口向外发送异步消息。异步消息的发送可以用于通知上层应用程序一些重要的事件,例如设备状态的变化或者错误情况的发生。

(二)命令处理机制

  1. 命令处理函数注册
    构造函数中还包含了命令处理函数的注册代码:
register_msg_cmd_handler(cmd_tag_key(),
                         [this](const pmt::pmt_t& tag, const int, const pmt::pmt_t&) {
                             this->_cmd_handler_tag(tag);
                         });

这里使用 register_msg_cmd_handler 函数注册了一个处理特定命令的函数。当接收到与 cmd_tag_key() 相关的命令消息时,会调用 lambda 表达式中定义的函数,最终执行 _cmd_handler_tag 函数。

  1. 命令处理函数 _cmd_handler_tag
void usrp_source_impl::_cmd_handler_tag(const pmt::pmt_t& tag) { _tag_now = true; }

_cmd_handler_tag 函数的作用是将 _tag_now 标记设置为 true。当数据接收正常且 _tag_now 为 true 时,会创建与数据相关的时间戳、采样率、中心频率等元信息标签,并将其添加到输出数据的相应通道上。这是因为当模块接收到异步消息时,设备参数或状态可能发生了改变,所以需要更新这些元信息以保证数据的准确性和完整性。然而,令人费解的是,usrp_source仅仅更新了 _tag_now ,却并未读取消息的任何具体内容,也没有依据usrp_source设置的举动。但更新_tag_now又表明 USRP 的设备参数或状态发生了改变,进而需要更新数据流标签
这其实是因为usrp_source的消息处理机制实际上继承自usrp_block的消息处理机制。

四、usrp_block的消息处理机制

(一)消息端口与命令注册

  1. 消息端口注册
    usrp_block_impl的构造函数中,通过如下代码注册了一个输入消息端口:
message_port_register_in(pmt::mp("command"));

这使得usrp_block能够接收来自外部的命令消息,为设备的参数设置和状态控制提供了入口。

  1. 命令处理函数注册
    构造函数中还大量使用宏定义来注册各种命令处理函数:
#define REGISTER_CMD_HANDLER(key, _handler)                                   \
    register_msg_cmd_handler(                                                 \
        key, [this](const pmt::pmt_t& var, int chan, const pmt::pmt_t& msg) { \
            this->_handler(var, chan, msg);                                   \
        })
// Register default command handlers:
REGISTER_CMD_HANDLER(cmd_freq_key(), _cmd_handler_freq);
REGISTER_CMD_HANDLER(cmd_gain_key(), _cmd_handler_gain);
REGISTER_CMD_HANDLER(cmd_power_key(), _cmd_handler_power);
// 其他命令处理函数注册...

通过register_msg_cmd_handler函数,将不同的命令关键字(如cmd_freq_keycmd_gain_key等)与对应的处理函数(如_cmd_handler_freq_cmd_handler_gain等)关联起来。当接收到包含这些命令关键字的消息时,相应的处理函数将被调用。

(二)命令消息处理流程

  1. 消息格式转换与校验
    msg_handler_command函数中,首先对接收到的消息进行处理。如果消息是元组格式(这是一种旧的消息格式),会将其转换为字典格式,以保证后续处理的一致性:
if (pmt::is_tuple(msg)) {
    if (pmt::length(msg) != 2 && pmt::length(msg) != 3) {
        d_logger->alert("Error while unpacking command PMT: {}",
                        pmt::write_string(msg));
        return;
    }
    pmt::pmt_t new_msg = pmt::make_dict();
    new_msg = pmt::dict_add(new_msg, pmt::tuple_ref(msg, 0), pmt::tuple_ref(msg, 1));
    if (pmt::length(msg) == 3) {
        new_msg = pmt::dict_add(new_msg, cmd_chan_key(), pmt::tuple_ref(msg, 2));
    }
    d_debug_logger->warn("Using legacy message format (tuples): {}",
                         pmt::write_string(msg));
    return msg_handler_command(new_msg);
}

接着,确保消息是字典格式,如果不是则记录错误并返回:

if (!(pmt::is_dict(msg)) && pmt::is_pair(msg)) {
    d_logger->debug(
        "Command message is pair, converting to dict: '{}': car({}), cdr({})",
        pmt::write_string(msg),
        pmt::car(msg),
        pmt::cdr(msg));
    msg = pmt::dict_add(pmt::make_dict(), pmt::car(msg), pmt::cdr(msg));
}
if (!pmt::is_dict(msg)) {
    d_logger->error("Command message is neither dict nor pair: {}",
                    pmt::write_string(msg));
    return;
}
  1. 消息内容处理
  • 时间戳处理:如果消息中包含时间戳相关的关键字cmd_time_key,则根据消息中的时间信息设置设备的命令时间:
if (pmt::dict_has_key(msg, cmd_time_key())) {
    size_t mboard_index = pmt::to_long(pmt::dict_ref(
        msg,
        cmd_mboard_key(),
        pmt::from_long(::uhd::usrp::multi_usrp::ALL_MBOARDS) // Default to all mboards
        ));
    pmt::pmt_t timespec_p = pmt::dict_ref(msg, cmd_time_key(), pmt::PMT_NIL);
    if (timespec_p == pmt::PMT_NIL) {
        clear_command_time(mboard_index);
    } else {
        ::uhd::time_spec_t timespec(
            time_t(pmt::to_uint64(pmt::car(timespec_p))), // Full secs
            pmt::to_double(pmt::cdr(timespec_p))          // Frac secs
        );
        d_debug_logger->debug("Setting command time on mboard {}", mboard_index);
        set_command_time(timespec, mboard_index);
    }
}
  • 通道与方向处理:读取消息中的通道号chan和方向信息,方向信息会影响设备参数设置的目标方向(如接收或发送),并且方向信息的存在可能会强制设备进行频率调谐:
int chan = int(pmt::to_long(pmt::dict_ref(msg,
                                          cmd_chan_key(),
                                          pmt::from_long(-1) // Default to all chans
                                          )));
_force_tune = pmt::dict_has_key(msg, cmd_direction_key());
  • 命令值处理:遍历消息中的所有键值对,根据命令关键字调用相应的处理函数进行处理:
pmt::pmt_t msg_items = pmt::dict_items(msg);
for (size_t i = 0; i < pmt::length(msg_items); i++) {
    try {
        dispatch_msg_cmd_handler(pmt::car(pmt::nth(i, msg_items)),
                                 pmt::cdr(pmt::nth(i, msg_items)),
                                 chan,
                                 msg);
    } catch (pmt::wrong_type& e) {
        d_logger->alert("Invalid command value for key {}: {}",
                        pmt::write_string(pmt::car(pmt::nth(i, msg_items))),
                        pmt::write_string(pmt::cdr(pmt::nth(i, msg_items))));
        break;
    }
}

dispatch_msg_cmd_handler函数中,根据之前注册的命令处理函数映射表_msg_cmd_handlers,调用对应的处理函数:

void usrp_block_impl::dispatch_msg_cmd_handler(const pmt::pmt_t& cmd,
                                               const pmt::pmt_t& val,
                                               int chan,
                                               pmt::pmt_t& msg)
{
    if (_msg_cmd_handlers.has_key(cmd)) {
        _msg_cmd_handlers[cmd](val, chan, msg);
    }
}

例如,_cmd_handler_freq函数用于处理频率相关的命令消息,它会根据消息中的频率值和其他相关信息(如本振偏移)更新设备的调谐请求:

void usrp_block_impl::_cmd_handler_freq(const pmt::pmt_t& freq_,
                                        int chan,
                                        const pmt::pmt_t& msg)
{
    const pmt::pmt_t direction = get_cmd_or_default_direction(msg);
    double freq = pmt::to_double(freq_);
    ::uhd::tune_request_t new_tune_request(freq);
    if (pmt::dict_has_key(msg, cmd_lo_offset_key())) {
        double lo_offset =
            pmt::to_double(pmt::dict_ref(msg, cmd_lo_offset_key(), pmt::PMT_NIL));
        new_tune_request = ::uhd::tune_request_t(freq, lo_offset);
    }
    _update_curr_tune_req(new_tune_request, chan, direction);
}

_update_curr_tune_req函数会根据通道号和方向,更新当前的调谐请求,并标记相应通道需要重新调谐:

void usrp_block_impl::_update_curr_tune_req(::uhd::tune_request_t& tune_req,
                                            int chan,
                                            pmt::pmt_t direction)
{
    if (chan == -1) {
        for (size_t i = 0; i < _nchan; i++) {
            _update_curr_tune_req(tune_req, int(i), direction);
        }
        return;
    }
    if (pmt::eqv(direction, direction_rx())) {
        if (tune_req.target_freq != _curr_rx_tune_req[chan].target_freq ||
            // 其他条件判断
            _force_tune) {
            _curr_rx_tune_req[chan] = tune_req;
            _rx_chans_to_tune[chan] = true;
        }
    } else {
        // 类似的发送方向处理
    }
}
  • 频率调谐检查:在处理完所有命令消息后,检查是否需要对所有通道进行频率调谐,并执行相应的调谐操作:
_set_center_freq_from_internals_allchans();
_force_tune = false;

_set_center_freq_from_internals_allchans函数会遍历所有通道,根据之前标记的需要调谐的通道,执行实际的频率设置操作:

void usrp_block_impl::_set_center_freq_from_internals_allchans()
{
    for (size_t chan = 0; chan < _rx_chans_to_tune.size(); chan++) {
        if (_rx_chans_to_tune[chan]) {
            _set_center_freq_from_internals(chan, direction_rx());
            _rx_chans_to_tune[chan] = false;
        }
    }
    for (size_t chan = 0; chan < _tx_chans_to_tune.size(); chan++) {
        if (_tx_chans_to_tune[chan]) {
            _set_center_freq_from_internals(chan, direction_tx());
            _tx_chans_to_tune[chan] = false;
        }
    }
}

四、总结

usrp_source 的消息处理机制通过消息端口的注册与管理、命令处理函数的设置以及错误消息的处理等多个环节协同工作。此外,还需要注意usrp_source通过继承usrp_block的消息处理机制,在接收到消息后,虽然表面上只是更新了_tag_now,但实际上是依赖usrp_block内部复杂的命令处理流程来修改设备参数。usrp_block负责接收、解析和处理各种命令消息,包括设备的频率、增益、功率、天线等参数的设置,以及时间同步、GPIO控制等操作。这种分层的消息处理机制,使得usrp_source能够专注于数据获取功能,而将消息处理的重任交给usrp_block,提高了代码的模块化和可维护性。

#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # SPDX-License-Identifier: GPL-3.0 # # GNU Radio Python Flow Graph # Title: DT_M003_QPSK # Author: digitech # GNU Radio version: 3.10.7.0 from packaging.version import Version as StrictVersion from PyQt5 import Qt from gnuradio import qtgui from gnuradio import blocks import pmt from gnuradio import digital from gnuradio import gr from gnuradio.filter import firdes from gnuradio.fft import window import sys import signal from PyQt5 import Qt from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation from gnuradio import uhd import time from gnuradio.qtgui import Range, RangeWidget from PyQt5 import QtCore import sip class DT_M003_QPSK(gr.top_block, Qt.QWidget): def __init__(self, HdrFormat=digital.header_format_default(digital.packet_utils.default_access_code, 0)): gr.top_block.__init__(self, "DT_M003_QPSK", catch_exceptions=True) Qt.QWidget.__init__(self) self.setWindowTitle("DT_M003_QPSK") 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", "DT_M003_QPSK") try: if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): self.restoreGeometry(self.settings.value("geometry").toByteArray()) else: self.restoreGeometry(self.settings.value("geometry")) except BaseException as exc: print(f"Qt GUI: Could not restore geometry: {str(exc)}", file=sys.stderr) ################################################## # Parameters ################################################## self.HdrFormat = HdrFormat ################################################## # Variables ################################################## self.sps = sps = 15 self.nfilts = nfilts = 128 self.timing_loop_bandwidth = timing_loop_bandwidth = .062 self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), 0.35, 45*nfilts) self.TxGain = TxGain = 75 self.TxCenterFreq = TxCenterFreq = 136000000 self.SampleRateUSRP = SampleRateUSRP = 1000000 self.SampleRate = SampleRate = 100000 self.RxGain = RxGain = 60 self.RxCenterFreq = RxCenterFreq = 291400000 self.QPSK = QPSK = digital.constellation_calcdist(digital.psk_4()[0], digital.psk_4()[1], 4, 1, digital.constellation.AMPLITUDE_NORMALIZATION).base() ################################################## # Blocks ################################################## self._timing_loop_bandwidth_range = Range(.001, .2, .001, .062, 200) self._timing_loop_bandwidth_win = RangeWidget(self._timing_loop_bandwidth_range, self.set_timing_loop_bandwidth, "'timing_loop_bandwidth'", "counter_slider", float, QtCore.Qt.Horizontal) self.top_layout.addWidget(self._timing_loop_bandwidth_win) self._TxGain_range = Range(20, 100, 1, 75, 200) self._TxGain_win = RangeWidget(self._TxGain_range, self.set_TxGain, "'TxGain'", "counter_slider", float, QtCore.Qt.Horizontal) self.top_layout.addWidget(self._TxGain_win) self._RxGain_range = Range(20, 100, 1, 60, 200) self._RxGain_win = RangeWidget(self._RxGain_range, self.set_RxGain, "'RxGain'", "counter_slider", float, QtCore.Qt.Horizontal) self.top_layout.addWidget(self._RxGain_win) self.uhd_usrp_source_0 = uhd.usrp_source( ",".join(("name: MyB200", '')), uhd.stream_args( cpu_format="fc32", args='', channels=list(range(0,1)), ), ) self.uhd_usrp_source_0.set_samp_rate(SampleRateUSRP) self.uhd_usrp_source_0.set_time_unknown_pps(uhd.time_spec(0)) self.uhd_usrp_source_0.set_center_freq(RxCenterFreq, 0) self.uhd_usrp_source_0.set_antenna("RX2", 0) self.uhd_usrp_source_0.set_rx_agc(False, 0) self.uhd_usrp_source_0.set_gain(RxGain, 0) self.uhd_usrp_source_0.set_auto_dc_offset(True, 0) self.uhd_usrp_source_0.set_auto_iq_balance(True, 0) self.uhd_usrp_sink_0 = uhd.usrp_sink( ",".join(("name: MyB200", "")), uhd.stream_args( cpu_format="fc32", args='', channels=list(range(0,1)), ), "", ) self.uhd_usrp_sink_0.set_samp_rate(SampleRateUSRP) self.uhd_usrp_sink_0.set_time_unknown_pps(uhd.time_spec(0)) self.uhd_usrp_sink_0.set_center_freq(TxCenterFreq, 0) self.uhd_usrp_sink_0.set_antenna("TX/RX", 0) self.uhd_usrp_sink_0.set_bandwidth(1000000, 0) self.uhd_usrp_sink_0.set_gain(TxGain, 0) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 1024, #size window.WIN_BLACKMAN_hARRIS, #wintype 0, #fc 10000000, #bw 'QPSK TX', #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.qtgui_const_sink_x_0 = qtgui.const_sink_c( 1024, #size "", #name 1, #number of inputs None # parent ) self.qtgui_const_sink_x_0.set_update_time(0.10) self.qtgui_const_sink_x_0.set_y_axis((-2), 2) self.qtgui_const_sink_x_0.set_x_axis((-2), 2) self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "") self.qtgui_const_sink_x_0.enable_autoscale(False) self.qtgui_const_sink_x_0.enable_grid(False) self.qtgui_const_sink_x_0.enable_axis_labels(True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = ["blue", "red", "red", "red", "red", "red", "red", "red", "red", "red"] styles = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] markers = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 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_const_sink_x_0.set_line_label(i, "Data {0}".format(i)) else: self.qtgui_const_sink_x_0.set_line_label(i, labels[i]) self.qtgui_const_sink_x_0.set_line_width(i, widths[i]) self.qtgui_const_sink_x_0.set_line_color(i, colors[i]) self.qtgui_const_sink_x_0.set_line_style(i, styles[i]) self.qtgui_const_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.qwidget(), Qt.QWidget) self.top_layout.addWidget(self._qtgui_const_sink_x_0_win) self.digital_protocol_formatter_bb_0_0_0 = digital.protocol_formatter_bb(HdrFormat, "packet_len") self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bandwidth, rrc_taps, nfilts, (nfilts/2), 1.5, 1) self.digital_map_bb_0 = digital.map_bb(digital.psk_4()[1]) self.digital_costas_loop_cc_0 = digital.costas_loop_cc(0.068, 4, False) self.digital_correlate_access_code_xx_ts_1 = digital.correlate_access_code_bb_ts(digital.packet_utils.default_access_code, 0, 'len_key2') self.digital_constellation_modulator_0 = digital.generic_mod( constellation=QPSK, differential=False, samples_per_symbol=sps, pre_diff_code=True, excess_bw=0.35, verbose=False, log=False, truncate=False) self.digital_constellation_decoder_cb_0 = digital.constellation_decoder_cb(QPSK) self.blocks_unpacked_to_packed_xx_1 = blocks.unpacked_to_packed_bb(2, gr.GR_MSB_FIRST) self.blocks_unpacked_to_packed_xx_0 = blocks.unpacked_to_packed_bb(2, gr.GR_MSB_FIRST) self.blocks_tagged_stream_mux_0_0_0 = blocks.tagged_stream_mux(gr.sizeof_char*1, "packet_len", 0) self.blocks_stream_to_tagged_stream_0_0_0 = blocks.stream_to_tagged_stream(gr.sizeof_char, 1, 19, "packet_len") self.blocks_repack_bits_bb_1_0_0 = blocks.repack_bits_bb(8, 1, "", False, gr.GR_MSB_FIRST) self.blocks_repack_bits_bb_1_0 = blocks.repack_bits_bb(1, 8, "", False, gr.GR_MSB_FIRST) self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(8, 2, "", False, gr.GR_MSB_FIRST) self.blocks_file_source_0 = blocks.file_source(gr.sizeof_char*1, './text.txt', True, 0, 0) self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL) self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, './out.txt', False) self.blocks_file_sink_0.set_unbuffered(False) ################################################## # Connections ################################################## self.connect((self.blocks_file_source_0, 0), (self.blocks_stream_to_tagged_stream_0_0_0, 0)) self.connect((self.blocks_repack_bits_bb_0, 0), (self.blocks_unpacked_to_packed_xx_1, 0)) self.connect((self.blocks_repack_bits_bb_1_0, 0), (self.blocks_file_sink_0, 0)) self.connect((self.blocks_repack_bits_bb_1_0_0, 0), (self.digital_correlate_access_code_xx_ts_1, 0)) self.connect((self.blocks_stream_to_tagged_stream_0_0_0, 0), (self.blocks_tagged_stream_mux_0_0_0, 1)) self.connect((self.blocks_stream_to_tagged_stream_0_0_0, 0), (self.digital_protocol_formatter_bb_0_0_0, 0)) self.connect((self.blocks_tagged_stream_mux_0_0_0, 0), (self.blocks_repack_bits_bb_0, 0)) self.connect((self.blocks_unpacked_to_packed_xx_0, 0), (self.blocks_repack_bits_bb_1_0_0, 0)) self.connect((self.blocks_unpacked_to_packed_xx_1, 0), (self.digital_constellation_modulator_0, 0)) self.connect((self.digital_constellation_decoder_cb_0, 0), (self.digital_map_bb_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.uhd_usrp_sink_0, 0)) self.connect((self.digital_correlate_access_code_xx_ts_1, 0), (self.blocks_repack_bits_bb_1_0, 0)) self.connect((self.digital_costas_loop_cc_0, 0), (self.digital_constellation_decoder_cb_0, 0)) self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_0, 0)) self.connect((self.digital_map_bb_0, 0), (self.blocks_unpacked_to_packed_xx_0, 0)) self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_costas_loop_cc_0, 0)) self.connect((self.digital_protocol_formatter_bb_0_0_0, 0), (self.blocks_tagged_stream_mux_0_0_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0)) def closeEvent(self, event): self.settings = Qt.QSettings("GNU Radio", "DT_M003_QPSK") self.settings.setValue("geometry", self.saveGeometry()) self.stop() self.wait() event.accept() def get_HdrFormat(self): return self.HdrFormat def set_HdrFormat(self, HdrFormat): self.HdrFormat = HdrFormat def get_sps(self): return self.sps def set_sps(self, sps): self.sps = sps self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.0/float(self.sps), 0.35, 45*self.nfilts)) def get_nfilts(self): return self.nfilts def set_nfilts(self, nfilts): self.nfilts = nfilts self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.0/float(self.sps), 0.35, 45*self.nfilts)) def get_timing_loop_bandwidth(self): return self.timing_loop_bandwidth def set_timing_loop_bandwidth(self, timing_loop_bandwidth): self.timing_loop_bandwidth = timing_loop_bandwidth self.digital_pfb_clock_sync_xxx_0.set_loop_bandwidth(self.timing_loop_bandwidth) def get_rrc_taps(self): return self.rrc_taps def set_rrc_taps(self, rrc_taps): self.rrc_taps = rrc_taps self.digital_pfb_clock_sync_xxx_0.update_taps(self.rrc_taps) def get_TxGain(self): return self.TxGain def set_TxGain(self, TxGain): self.TxGain = TxGain self.uhd_usrp_sink_0.set_gain(self.TxGain, 0) def get_TxCenterFreq(self): return self.TxCenterFreq def set_TxCenterFreq(self, TxCenterFreq): self.TxCenterFreq = TxCenterFreq self.uhd_usrp_sink_0.set_center_freq(self.TxCenterFreq, 0) def get_SampleRateUSRP(self): return self.SampleRateUSRP def set_SampleRateUSRP(self, SampleRateUSRP): self.SampleRateUSRP = SampleRateUSRP self.uhd_usrp_sink_0.set_samp_rate(self.SampleRateUSRP) self.uhd_usrp_source_0.set_samp_rate(self.SampleRateUSRP) def get_SampleRate(self): return self.SampleRate def set_SampleRate(self, SampleRate): self.SampleRate = SampleRate def get_RxGain(self): return self.RxGain def set_RxGain(self, RxGain): self.RxGain = RxGain self.uhd_usrp_source_0.set_gain(self.RxGain, 0) def get_RxCenterFreq(self): return self.RxCenterFreq def set_RxCenterFreq(self, RxCenterFreq): self.RxCenterFreq = RxCenterFreq self.uhd_usrp_source_0.set_center_freq(self.RxCenterFreq, 0) def get_QPSK(self): return self.QPSK def set_QPSK(self, QPSK): self.QPSK = QPSK self.digital_constellation_decoder_cb_0.set_constellation(self.QPSK) def argument_parser(): parser = ArgumentParser() return parser def main(top_block_cls=DT_M003_QPSK, options=None): if options is None: options = argument_parser().parse_args() 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()
最新发布
07-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值