[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 02/04: uhd: uhd_rx_cfile updates
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 02/04: uhd: uhd_rx_cfile updates |
Date: |
Sun, 13 Sep 2015 15:17:45 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
jcorgan pushed a commit to branch master
in repository gnuradio.
commit 7ab2c36ffb7631464fef77bd12a067bf51d32c7b
Author: Martin Braun <address@hidden>
Date: Fri Jun 26 21:02:56 2015 -0700
uhd: uhd_rx_cfile updates
- Multi-channel receive operation
- Better phase alignment where possible
- E310 verbose output fix
- Normalized gain
- Minor bugfixes
---
gr-uhd/apps/uhd_rx_cfile | 263 +++++++++++++++++++++++------------------
gr-uhd/lib/usrp_source_impl.cc | 4 +-
2 files changed, 153 insertions(+), 114 deletions(-)
diff --git a/gr-uhd/apps/uhd_rx_cfile b/gr-uhd/apps/uhd_rx_cfile
old mode 100644
new mode 100755
index 442dd46..80bbc87
--- a/gr-uhd/apps/uhd_rx_cfile
+++ b/gr-uhd/apps/uhd_rx_cfile
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2012,2013 Free Software Foundation, Inc.
+# Copyright 2012,2013,2015 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -26,103 +26,143 @@ outputs single precision complex float values or complex
short values
(interleaved 16 bit signed short integers).
"""
+import sys
+import os
+import pmt
+import time
from gnuradio import gr, gru, eng_notation
from gnuradio import blocks
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from optparse import OptionParser
-import pmt
-import sys
n2s = eng_notation.num_to_str
+COMMAND_DELAY = .2
class rx_cfile_block(gr.top_block):
-
+ """
+ Simple flowgraph that streams from USRP source to file.
+ """
def __init__(self, options, filename):
gr.top_block.__init__(self)
-
- # Create a UHD device source
- if options.output_shorts:
- self._u = uhd.usrp_source(device_addr=options.args,
stream_args=uhd.stream_args('sc16',
- options.wire_format,
args=options.stream_args))
+ # Dissect the channel list:
+ try:
+ self.channels = [int(x.strip()) for x in
options.channels.split(",")]
+ except ValueError:
+ sys.stderr.write("[UHD_RX] [ERROR] Invalid channel list:
{}".format(options.channels))
+ exit(1)
+ # Create file names:
+ if len(self.channels) == 1:
+ self.filenames = [filename,]
else:
- self._u = uhd.usrp_source(device_addr=options.args,
stream_args=uhd.stream_args('fc32',
- options.wire_format,
args=options.stream_args))
-
- # Set the subdevice spec
- if(options.spec):
- self._u.set_subdev_spec(options.spec, 0)
-
- # Set the antenna
- if(options.antenna):
- self._u.set_antenna(options.antenna, 0)
-
- # Set receiver sample rate
+ base, ext = os.path.splitext(filename)
+ self.filenames = []
+ for i in range(len(self.channels)):
+ self.filenames.append("{base}.{num}{ext}".format(base=base,
num=i, ext=ext))
+ # Check CPU format:
+ self.cpu_format = 'fc32'
+ self.item_size = gr.sizeof_gr_complex
+ self.meta_file_type = blocks.GR_FILE_FLOAT
+ if options.output_shorts:
+ self.cpu_format = 'sc16'
+ self.item_size = gr.sizeof_short * 2
+ self.meta_file_type = blocks.GR_FILE_SHORT
+ # Create a UHD device source:
+ self._u = uhd.usrp_source(
+ device_addr=options.args,
+ stream_args=uhd.stream_args(
+ self.cpu_format,
+ options.wire_format,
+ args=options.stream_args,
+ channels=self.channels,
+ )
+ )
+ # Set the subdevice spec:
+ if options.spec:
+ for mb_idx in xrange(self._u.get_num_mboards()):
+ self._u.set_subdev_spec(options.spec, mb_idx)
+ # Set the antenna:
+ self.antenna = [x.strip() for x in options.antenna.split(",")]
+ if len(self.antenna) != 1 and len(self.antenna) != len(self.channels):
+ sys.stderr.write("[UHD_RX] [ERROR] Invalid antenna setting for {}
channels: {}".format(
+ len(self.channels), options.antenna
+ ))
+ exit(1)
+ if len(self.antenna) == 1 and len(self.channels) > 1:
+ self.antenna = [self.antenna[0],] * len(self.channels)
+ for i, chan in enumerate(self.channels):
+ self._u.set_antenna(self.antenna[i], chan)
+ if options.verbose:
+ print("[UHD_RX] Channel {chan}: Using antenna {ant}.".format(
+ chan=chan, ant=self._u.get_antenna(chan)
+ ))
+ # Set receiver sample rate:
self._u.set_samp_rate(options.samp_rate)
samp_rate = self._u.get_samp_rate()
-
- # Set receive daughterboard gain
+ # Set receive daughterboard gain:
if options.gain is None:
- g = self._u.get_gain_range()
- options.gain = float(g.start()+g.stop())/2
- print "Using mid-point gain of", options.gain, "(", g.start(), "-",
g.stop(), ")"
- self._u.set_gain(options.gain)
- gain = self._u.get_gain()
-
- # Set frequency (tune request takes lo_offset)
- if(options.lo_offset is not None):
+ print("[UHD_RX] Defaulting to mid-point gains:")
+ for chan in self.channels:
+ self._u.set_normalized_gain(.5, chan)
+ print("[UHD_RX] Channel {chan} gain: {g} dB".format(chan=chan,
g=self._u.get_gain(chan)))
+ else:
+ for chan in self.channels:
+ self._u.set_gain(options.gain, chan)
+ gain = self._u.get_gain(self.channels[0])
+ # Set frequency (tune request takes lo_offset):
+ if options.lo_offset is not None:
treq = uhd.tune_request(options.freq, options.lo_offset)
else:
treq = uhd.tune_request(options.freq)
- tr = self._u.set_center_freq(treq)
- if tr == None:
- sys.stderr.write('Failed to set center frequency\n')
- raise SystemExit, 1
- freq = self._u.get_center_freq()
-
- # Create file sink
- if options.metafile:
- # store additional metadata
- extras = pmt.make_dict()
- extras = pmt.dict_add(extras, pmt.intern("rx_gain"),
pmt.from_double(gain))
- extras_str = pmt.serialize_str(extras)
- if options.output_shorts:
- self._sink = blocks.file_meta_sink(gr.sizeof_short * 2,
filename,
- samp_rate, 1,
- blocks.GR_FILE_SHORT, True,
- 1000000, extras_str, False)
- else:
- self._sink = blocks.file_meta_sink(gr.sizeof_gr_complex,
filename,
- samp_rate, 1,
- blocks.GR_FILE_FLOAT, True,
- 1000000, extras_str, False)
- else:
- if options.output_shorts:
- self._sink = blocks.file_sink(gr.sizeof_short*2, filename)
+ # Make sure tuning is synched:
+ if len(self.channels) > 1:
+ if options.sync == 'pps':
+ self._u.set_time_unknown_pps(uhd.time_spec())
+ cmd_time = self._u.get_time_now() + uhd.time_spec(COMMAND_DELAY)
+ for mb_idx in xrange(self._u.get_num_mboards()):
+ self._u.set_command_time(cmd_time, mb_idx)
+ for chan in self.channels:
+ tr = self._u.set_center_freq(treq, chan)
+ if tr == None:
+ sys.stderr.write('[UHD_RX] [ERROR] Failed to set center
frequency on channel {chan}\n'.format(chan=chan))
+ exit(1)
+ if len(self.channels) > 1:
+ for mb_idx in xrange(self._u.get_num_mboards()):
+ self._u.clear_command_time(mb_idx)
+ print("[UHD_RX] Syncing channels...")
+ time.sleep(COMMAND_DELAY)
+ freq = self._u.get_center_freq(self.channels[0])
+ # Create file sink(s):
+ self._sink = []
+ for i in range(len(self.channels)):
+ if options.metafile:
+ # store additional metadata
+ extras = pmt.make_dict()
+ extras = pmt.dict_add(extras, pmt.intern("rx_gain"),
pmt.from_double(gain))
+ extras_str = pmt.serialize_str(extras)
+ self._sink.append(blocks.file_meta_sink(
+ self.item_size, self.filenames[i],
+ samp_rate, 1,
+ self.meta_file_type, True,
+ 1000000, extras_str, False
+ ))
else:
- self._sink = blocks.file_sink(gr.sizeof_gr_complex, filename)
-
- # Create head block if needed and wire it up
- if options.nsamples is None:
- self.connect(self._u, self._sink)
- else:
- if options.output_shorts:
- self._head = blocks.head(gr.sizeof_short*2,
int(options.nsamples))
+ self._sink.append(blocks.file_sink(self.item_size,
self.filenames[i]))
+ # Create head block if needed and wire it up:
+ if options.nsamples is None:
+ self.connect((self._u, i), self._sink[i])
else:
- self._head = blocks.head(gr.sizeof_gr_complex,
int(options.nsamples))
-
- self.connect(self._u, self._head, self._sink)
-
+ self._head = blocks.head(self.item_size, int(options.nsamples))
+ self.connect((self._u, i), self._head, self._sink[i])
+ # Output status info if requested:
if options.verbose:
try:
info = self._u.get_usrp_info()
-
mboard_id = info["mboard_id"].split(" ")[0]
if info["mboard_serial"] == "":
mboard_serial = "no serial"
else:
mboard_serial = info["mboard_serial"]
-
rx_id = info["rx_id"].split(" ")[0]
if info["rx_serial"] == "":
rx_serial = "no serial"
@@ -130,30 +170,29 @@ class rx_cfile_block(gr.top_block):
rx_serial = info["rx_serial"]
rx_antenna = info["rx_antenna"]
rx_subdev_spec = info["rx_subdev_spec"]
-
- print "Motherboard: %s (%s)" % (mboard_id, mboard_serial)
- if "B200" in mboard_id or "B210" in mboard_id:
- print "Daughterboard: %s (%s, %s)" % (mboard_id,
rx_antenna, rx_subdev_spec)
+ print "[UHD_RX] Motherboard: %s (%s)" % (mboard_id,
mboard_serial)
+ if "B200" in mboard_id or "B210" in mboard_id or "E310" in
mboard_id:
+ print "[UHD_RX] Daughterboard: %s (%s, %s)" % (mboard_id,
rx_antenna, rx_subdev_spec)
else:
- print "Daughterboard: %s (%s, %s, %s)" % (rx_id,
rx_serial, rx_antenna, rx_subdev_spec)
- except:
- print "Args: ", options.args
-
- print "Rx gain:", options.gain
- print "Rx baseband frequency:", n2s(tr.actual_rf_freq)
- print "Rx DDC frequency:", n2s(tr.actual_dsp_freq)
- print "Rx Sample Rate:", n2s(samp_rate)
+ print "[UHD_RX] Daughterboard: %s (%s, %s, %s)" % (rx_id,
rx_serial, rx_antenna, rx_subdev_spec)
+ except KeyError:
+ print "[UHD_RX] Args: ", options.args
+ print("[UHD_RX] Receiving on {}
channels.".format(len(self.channels)))
+ print("[UHD_RX] Rx gain: {gain}".format(gain=gain))
+ print("[UHD_RX] Rx frequency: {freq}".format(freq=freq))
+ print("[UHD_RX] Rx baseband frequency:
{actual}".format(actual=n2s(tr.actual_rf_freq)))
+ print("[UHD_RX] Rx DDC frequency:
{dsp}".format(dsp=n2s(tr.actual_dsp_freq)))
+ print("[UHD_RX] Rx Sample Rate:
{rate}".format(rate=n2s(samp_rate)))
if options.nsamples is None:
- print "Receiving samples until Ctrl-C"
+ print("[UHD_RX] Receiving samples until Ctrl-C")
else:
- print "Receving", n2s(options.nsamples), "samples"
+ print("[UHD_RX] Receiving {n}
samples.".format(n2s(options.nsamples)))
if options.output_shorts:
- print "Writing 16-bit complex shorts"
+ print("[UHD_RX] Writing 16-bit complex shorts")
else:
- print "Writing 32-bit complex floats"
- print "Output filename:", filename
-
- # Direct asynchronous notifications to callback function
+ print("[UHD_RX] Writing 32-bit complex floats")
+ print("[UHD_RX] Output file(s): {files}".format(files=",
".join(self.filenames)))
+ # Direct asynchronous notifications to callback function:
if options.show_async_msg:
self.async_msgq = gr.msg_queue(0)
self.async_src = uhd.amsg_source("", self.async_msgq)
@@ -161,8 +200,7 @@ class rx_cfile_block(gr.top_block):
def async_callback(self, msg):
md = self.async_src.msg_to_async_metadata_t(msg)
- print "Channel: %i Time: %f Event: %i" % (md.channel,
md.time_spec.get_real_secs(), md.event_code)
-
+ print("[UHD_RX] Channel: %i Time: %f Event: %i" % (md.channel,
md.time_spec.get_real_secs(), md.event_code))
def get_options():
usage="%prog: [options] output_filename"
@@ -171,49 +209,50 @@ def get_options():
help="UHD device address args , [default=%default]")
parser.add_option("", "--spec", type="string", default=None,
help="Subdevice of UHD device where appropriate")
+ parser.add_option("-c", "--channels", type="string", default="0",
+ help="Select receive channels")
parser.add_option("-A", "--antenna", type="string", default=None,
- help="select Rx Antenna where appropriate")
- parser.add_option("", "--samp-rate", type="eng_float", default=1e6,
- help="set sample rate (bandwidth) [default=%default]")
+ help="Select Rx Antenna(s) where appropriate.\nUse a
comma-delimited list if different channels have different antenna ports.")
+ parser.add_option("-r", "--samp-rate", type="eng_float", default=1e6,
+ help="Set sample rate (bandwidth) [default=%default]")
parser.add_option("-f", "--freq", type="eng_float", default=None,
- help="set frequency to FREQ", metavar="FREQ")
+ help="Set frequency to FREQ", metavar="FREQ")
+ parser.add_option("", "--lo-offset", type="eng_float", default=None,
+ help="Set daughterboard LO offset to OFFSET [default=hw
default]")
parser.add_option("-g", "--gain", type="eng_float", default=None,
- help="set gain in dB (default is midpoint)")
+ help="Set gain in dB (default is midpoint)")
+ parser.add_option("--normalized-gain", action="store_true",
+ help="Specify gain as normalized value (in [0, 1])")
parser.add_option( "-m","--metafile", action="store_true", default=False,
help="output metadata to file [default=%default]")
parser.add_option( "-s","--output-shorts", action="store_true",
default=False,
- help="output interleaved shorts instead of complex
floats")
+ help="Output interleaved shorts instead of complex
floats")
parser.add_option("-N", "--nsamples", type="eng_float", default=None,
- help="number of samples to collect [default=+inf]")
+ help="Number of samples to collect [default=+inf]")
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="verbose output")
- parser.add_option("", "--lo-offset", type="eng_float", default=None,
- help="set daughterboard LO offset to OFFSET [default=hw
default]")
parser.add_option("", "--wire-format", type="string", default="sc16",
- help="set wire format from USRP [default=%default")
+ help="Set wire format from USRP [default=%default")
parser.add_option("", "--stream-args", type="string", default="",
- help="set stream arguments [default=%default]")
+ help="Set additional stream arguments")
parser.add_option("", "--show-async-msg", action="store_true",
default=False,
help="Show asynchronous message notifications from UHD
[default=%default]")
-
- (options, args) = parser.parse_args ()
+ parser.add_option("", "--sync", type="choice", choices=('default', 'pps'),
+ default='default', help="Set to 'pps' to sync devices to
PPS instead of internal.")
+ (options, args) = parser.parse_args()
if len(args) != 1:
parser.print_help()
- raise SystemExit, 1
-
+ exit(1)
if options.freq is None:
parser.print_help()
- sys.stderr.write('You must specify the frequency with -f FREQ\n');
- raise SystemExit, 1
-
+ sys.stderr.write('You must specify the frequency with -f FREQ\n')
+ exit(1)
return (options, args[0])
-
if __name__ == '__main__':
(options, filename) = get_options()
tb = rx_cfile_block(options, filename)
-
try:
tb.run()
except KeyboardInterrupt:
- pass
+ print("Receive terminated.")
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index 6f0283e..0514840 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -545,8 +545,8 @@ namespace gr {
return work(noutput_items, input_items, output_items);
default:
- std::cout << boost::format("UHD source block got error code 0x%x")
- % _metadata.error_code << std::endl;
+ //GR_LOG_WARN(d_logger, boost::format("USRP Source Block caught rx
error: %d") % _metadata.strerror());
+ GR_LOG_WARN(d_logger, boost::format("USRP Source Block caught rx error
code: %d") % _metadata.error_code);
return num_samps;
}