创建新模块:
gr_modtool newmod multiusrp
进入新模块所在文件夹:
cd gr-multiusrp/
添加一个source block:
gr_modtool add -t source -l python multiusrp_source
-t:为模块模式,有以下几种可选:‘sink’, ‘source’, ‘sync’, ‘decimator’, ‘interpolator’, ‘general’, ‘tagged_stream’, ‘hier’, ‘noblock’
-l:语言,有以下两种可选:cpp/python
修改文件./python/multiusrp_source.py:
import numpy
from gnuradio import gr
from gnuradio import blocks
import uhd
import numpy as np
import argparse
from datetime import datetime, timedelta
import sys
import time
import threading
import logging
from uhd import libpyuhd as lib
INIT_DELAY = 0.05
class multiusrp_source(gr.sync_block):
"""
docstring for block multiusrp_source
"""
def __init__(self, samp_rate, center_freq, gain, sources, duration):
gr.sync_block.__init__(self,
name="Multi Usrp Source",
in_sig=None,
out_sig=[numpy.complex64,numpy.complex64])
##################################################
# Parameters
##################################################
self.samp_rate = samp_rate
self.center_freq = center_freq
self.gain = gain
self.sources = sources
self.duration = duration
self.addresses = "addr=192.168.10.2"
self.subdev="A:0 B:0"
self.recvFile_0="../misc/rx00"
self.recvFile_1 = "../misc/rx01"
##################################################
# Blocks
##################################################
self.parameter = self.parse_args(self.addresses, center_freq, samp_rate, sources, gain, self.subdev)
self.usrp = uhd.usrp.MultiUSRP(self.parameter.args)
#self.num_samps = int(np.ceil(self.duration * self.samp_rate))
self.usrp.set_rx_subdev_spec(uhd.usrp.SubdevSpec(self.subdev))
self.usrp.set_clock_source("internal")
self.usrp.set_rx_dc_offset(0, 0)
self.usrp.set_rx_dc_offset(0, 1)
for chan in range(self.sources):
self.usrp.set_rx_rate(self.samp_rate,chan)
self.usrp.set_rx_freq(lib.types.tune_request(self.center_freq),chan)
self.usrp.set_rx_gain(self.gain,chan)
st_args=lib.usrp.stream_args("fc32","sc16")
st_args.channels=range(self.sources)
self.metadata=lib.types.rx_metadata()
self.streamer=self.usrp.get_rx_stream(st_args)
buffer_samps = self.streamer.get_max_num_samps()
self.recv_buffer = np.zeros((self.sources, buffer_samps), dtype=np.complex64)
stream_cmd = lib.types.stream_cmd(lib.types.stream_mode.start_cont)
stream_cmd.stream_now = False
stream_cmd.time_spec = uhd.types.TimeSpec(self.usrp.get_time_now().get_real_secs() + INIT_DELAY)
self.streamer.issue_stream_cmd(stream_cmd)
self.samps=np.array([],dtype=np.complex64)
def work(self, input_items, output_items):
out_0= output_items[0]
out_1 = output_items[1]
self.samps = self.streamer.recv(self.recv_buffer, self.metadata)
length=min(self.samps,len(out_0))
out_0[0:length] = self.recv_buffer[0, 0:length]
out_1[0:length] = self.recv_buffer[1, 0:length]
return length
def parse_args(self, addresses, center_freq, samp_rate, sources, gain, subdev):
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--args", default=addresses, type=str)
parser.add_argument("-f", "--freq", default=center_freq, type=int)
parser.add_argument("-r", "--rate", default=samp_rate, type=int)
parser.add_argument("-c", "--channels", default=range(sources), nargs="+", type=int)
parser.add_argument("--rx_cpu", type=str, default="fc32",
help="specify the host/cpu sample mode for RX")
parser.add_argument("--rx_otw", type=str, default="sc16",
help="specify the over-the-wire sample mode for RX")
parser.add_argument("-g", "--gain", type=int, default=gain)
return parser.parse_args()
修改./grc/multiusrp_multiusrp_source.xml:
<?xml version="1.0"?>
<block>
<name>multiusrp_source</name>
<key>multiusrp_multiusrp_source</key>
<category>multiusrp</category>
<import>import multiusrp</import>
<make>multiusrp.multiusrp_source($samp_rate, $center_freq, $gain, $sources, $duration)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>samp_rate</name>
<key>samp_rate</key>
<type>float</type>
</param>
<param>
<name>center_freq</name>
<key>center_freq</key>
<type>float</type>
</param>
<param>
<name>gain</name>
<key>gain</key>
<type>int</type>
</param>
<param>
<name>sources</name>
<key>sources</key>
<type>int</type>
</param>
<param>
<name>duration</name>
<key>duration</key>
<type>int</type>
</param>
<!-- Make one 'source' node per output. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<source>
<name>out_0</name>
<type>complex</type>
</source>
<source>
<name>out_1</name>
<type>complex</type>
</source>
</block>
添加一个sink block:
gr_modtool add -t sink -l python multiusrp_sink
修改文件./python/multiusrp_sink.py:
import numpy
from gnuradio import gr
import uhd
import numpy as np
import argparse
from datetime import datetime, timedelta
import sys
import time
import threading
import logging
from uhd import libpyuhd as lib
INIT_DELAY =1
class multiusrp_sink(gr.sync_block):
"""
docstring for block multiusrp_sink
"""
def __init__(self, samp_rate, center_freq, gain, sinks):
gr.sync_block.__init__(self,
name="Multi Usrp Sink",
in_sig=[numpy.complex64,numpy.complex64],
out_sig=None)
##################################################
# Parameters
##################################################
self.samp_rate = samp_rate
self.center_freq = center_freq
self.gain = gain
self.sink = sinks
self.addresses = "addr=192.168.10.2"
self.subdev="A:0 B:0"
self.tranFile_0="../misc/tran00"
##################################################
# Blocks
##################################################
self.parameter = self.parse_args(self.addresses, center_freq, samp_rate, sinks, gain, self.subdev)
self.usrp = uhd.usrp.MultiUSRP(self.parameter.args)
self.usrp.set_tx_subdev_spec(uhd.usrp.SubdevSpec(self.subdev))
self.usrp.set_clock_source("internal")
self.usrp.set_time_unknown_pps(uhd.types.TimeSpec(0.1))
for chan in range(self.sink):
self.usrp.set_tx_rate(self.samp_rate,chan)
self.usrp.set_tx_freq(lib.types.tune_request(self.center_freq),chan)
self.usrp.set_tx_gain(self.gain,chan)
st_args = uhd.usrp.StreamArgs("fc32","sc16")
st_args.channels = range(self.sink)
self.tx_streamer = self.usrp.get_tx_stream(st_args)
self.metadata = uhd.types.TXMetadata()
# Set false to send immediately.
# Set true to send at the time specified by time spec.
# self.metadata.has_time_spec = bool(num_channels)
self.metadata.time_spec = uhd.types.TimeSpec(self.usrp.get_time_now().get_real_secs() + INIT_DELAY)
self.metadata.has_time_spec = bool(self.sink)
# self.metadata.has_time_spec = True
# print("time:",self.usrp.get_time_now().get_real_secs() + INIT_DELAY)
self.tx_buffer_samps = self.tx_streamer.get_max_num_samps()
self.tx_buffer = np.zeros((self.sink, self.tx_buffer_samps), dtype=np.complex64)
# print(self.tx_buffer_samps)
# self.samps=np.array([],dtype=np.complex64)
def work(self, input_items, output_items):
# length=min(len(input_items[0]),len(input_items[1]))
# self.tx_buffer[0,0:self.tx_buffer_samps] = input_items[0,0:self.tx_buffer_samps]
# self.tx_buffer[1,0:self.tx_buffer_samps] = input_items[1,0:self.tx_buffer_samps]
self.samps= self.tx_streamer.send(input_items, self.metadata)
# self.metadata.time_spec = uhd.types.TimeSpec(self.usrp.get_time_now().get_real_secs()+0.05)
# print("time:", self.usrp.get_time_now().get_real_secs()+INIT_DELAY)
# with open(self.tranFile_0, 'wb') as f0:
# np.save(f0, in0[:], allow_pickle=False, fix_imports=False)
# print("samp:",self.samps)
return len(input_items[0])
def parse_args(self, addresses, center_freq, samp_rate, sinks, gain, subdev):
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--args", default=addresses, type=str)
parser.add_argument("-f", "--freq", default=center_freq, type=int)
parser.add_argument("-r", "--rate", default=samp_rate, type=int)
parser.add_argument("--tx_cpu", type=str, default="fc32",
help="specify the host/cpu sample mode for TX")
parser.add_argument("--tx_otw", type=str, default="sc16",
help="specify the over-the-wire sample mode for TX")
parser.add_argument("-g", "--gain", type=int, default=gain)
return parser.parse_args()
修改./grc/multiusrp_multiusrp_sink.xml:
<?xml version="1.0"?>
<block>
<name>multiusrp_sink</name>
<key>multiusrp_multiusrp_sink</key>
<category>multiusrp</category>
<import>import multiusrp</import>
<make>multiusrp.multiusrp_sink($samp_rate, $center_freq, $gain, $sinks)</make>
<!-- Make one 'param' node for every Parameter you want settable from the GUI.
Sub-nodes:
* name
* key (makes the value accessible as $keyname, e.g. in the make node)
* type -->
<param>
<name>samp_rate</name>
<key>samp_rate</key>
<type>float</type>
</param>
<param>
<name>center_freq</name>
<key>center_freq</key>
<type>float</type>
</param>
<param>
<name>gain</name>
<key>gain</key>
<type>int</type>
</param>
<param>
<name>sinks</name>
<key>sinks</key>
<type>int</type>
</param>
<!-- Make one 'sink' node per input. Sub-nodes:
* name (an identifier for the GUI)
* type
* vlen
* optional (set to 1 for optional inputs) -->
<sink>
<name>in_0</name>
<type>complex</type>
</sink>
<sink>
<name>in_1</name>
<type>complex</type>
</sink>
</block>
build:
mkdir build
cd build
sudo cmake ../
sudo make -j4
sudo make install
sudo ldconfig
此时在gnuradio中已经出现了multiusrp模块以及其下面的两个block。
那么如果模块不用了,如何卸载呢:
cd build
sudo make uninstall
sudo ldconfig
over!