Skip to content

Commit e91ae54

Browse files
committed
Merge branch 'master' into next
Conflicts: gr-uhd/lib/Makefile.am
2 parents 7eebbcd + 87c8751 commit e91ae54

8 files changed

+171
-15
lines changed

gr-uhd/include/gr_uhd_usrp_sink.h

+13
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ GR_UHD_API boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink(
117117
class GR_UHD_API uhd_usrp_sink : virtual public gr_sync_block{
118118
public:
119119

120+
/*!
121+
* Set the start time for outgoing samples.
122+
* To control when samples are transmitted,
123+
* set this value before starting the flow graph.
124+
* The value is cleared after each run.
125+
* When not specified, the start time will be:
126+
* - Immediately for the one channel case
127+
* - in the near future for multi-channel
128+
*
129+
* \param time the absolute time for transmission to begin
130+
*/
131+
virtual void set_start_time(const uhd::time_spec_t &time) = 0;
132+
120133
/*!
121134
* Set the frontend specification.
122135
* \param spec the subdev spec markup string

gr-uhd/include/gr_uhd_usrp_source.h

+27-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 Free Software Foundation, Inc.
2+
* Copyright 2010-2012 Free Software Foundation, Inc.
33
*
44
* This file is part of GNU Radio
55
*
@@ -109,6 +109,19 @@ GR_UHD_API boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source(
109109
class GR_UHD_API uhd_usrp_source : virtual public gr_sync_block{
110110
public:
111111

112+
/*!
113+
* Set the start time for incoming samples.
114+
* To control when samples are received,
115+
* set this value before starting the flow graph.
116+
* The value is cleared after each run.
117+
* When not specified, the start time will be:
118+
* - Immediately for the one channel case
119+
* - in the near future for multi-channel
120+
*
121+
* \param time the absolute time for reception to begin
122+
*/
123+
virtual void set_start_time(const uhd::time_spec_t &time) = 0;
124+
112125
/*!
113126
* Set the frontend specification.
114127
* \param spec the subdev spec markup string
@@ -469,10 +482,22 @@ class GR_UHD_API uhd_usrp_source : virtual public gr_sync_block{
469482
* Convenience function for finite data acquisition.
470483
* This is not to be used with the scheduler; rather,
471484
* one can request samples from the USRP in python.
472-
* //TODO multi-channel
473485
* //TODO assumes fc32
486+
* \param nsamps the number of samples
487+
* \return a vector of complex float samples
474488
*/
475489
virtual std::vector<std::complex<float> > finite_acquisition(const size_t nsamps) = 0;
490+
491+
/*!
492+
* Convenience function for finite data acquisition.
493+
* This is the multi-channel version of finite_acquisition;
494+
* This is not to be used with the scheduler; rather,
495+
* one can request samples from the USRP in python.
496+
* //TODO assumes fc32
497+
* \param nsamps the number of samples per channel
498+
* \return a vector of buffers, where each buffer represents a channel
499+
*/
500+
virtual std::vector<std::vector<std::complex<float> > > finite_acquisition_v(const size_t nsamps) = 0;
476501
};
477502

478503
#endif /* INCLUDED_GR_UHD_USRP_SOURCE_H */

gr-uhd/lib/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2011 Free Software Foundation, Inc.
1+
# Copyright 2011-2012 Free Software Foundation, Inc.
22
#
33
# This file is part of GNU Radio
44
#
@@ -23,6 +23,7 @@
2323
include_directories(
2424
${GNURADIO_CORE_INCLUDE_DIRS}
2525
${GR_UHD_INCLUDE_DIRS}
26+
${CMAKE_CURRENT_BINARY_DIR}
2627
)
2728

2829
include_directories(${UHD_INCLUDE_DIRS})

gr-uhd/lib/gr_uhd_amsg_source.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011 Free Software Foundation, Inc.
2+
* Copyright 2011-2012 Free Software Foundation, Inc.
33
*
44
* This file is part of GNU Radio
55
*
@@ -22,6 +22,7 @@
2222
#include <gr_uhd_amsg_source.h>
2323
#include <boost/bind.hpp>
2424
#include <gruel/thread.h>
25+
#include "gr_uhd_common.h"
2526

2627
/***********************************************************************
2728
* UHD Asynchronous Message Source Impl
@@ -87,6 +88,7 @@ boost::shared_ptr<uhd_amsg_source> uhd_make_amsg_source(
8788
const uhd::device_addr_t &device_addr,
8889
gr_msg_queue_sptr msgq
8990
){
91+
gr_uhd_check_abi();
9092
return boost::shared_ptr<uhd_amsg_source>(
9193
new uhd_amsg_source_impl(device_addr, msgq)
9294
);

gr-uhd/lib/gr_uhd_common.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2012 Free Software Foundation, Inc.
3+
*
4+
* This file is part of GNU Radio
5+
*
6+
* GNU Radio is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 3, or (at your option)
9+
* any later version.
10+
*
11+
* GNU Radio is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with GNU Radio; see the file COPYING. If not, write to
18+
* the Free Software Foundation, Inc., 51 Franklin Street,
19+
* Boston, MA 02110-1301, USA.
20+
*/
21+
22+
#ifndef INCLUDED_GR_UHD_COMMON_H
23+
#define INCLUDED_GR_UHD_COMMON_H
24+
25+
#include <uhd/version.hpp>
26+
#include <boost/format.hpp>
27+
#include <stdexcept>
28+
29+
static inline void gr_uhd_check_abi(void){
30+
#ifdef UHD_VERSION_ABI_STRING
31+
if (std::string(UHD_VERSION_ABI_STRING) == uhd::get_abi_string()) return;
32+
throw std::runtime_error(str(boost::format(
33+
"\nGR-UHD detected ABI compatibility mismatch with UHD library.\n"
34+
"GR-UHD was build against ABI: %s,\n"
35+
"but UHD library reports ABI: %s\n"
36+
"Suggestion: install an ABI compatible version of UHD,\n"
37+
"or rebuild GR-UHD component against this ABI version.\n"
38+
) % UHD_VERSION_ABI_STRING % uhd::get_abi_string()));
39+
#endif
40+
}
41+
42+
#endif /* INCLUDED_GR_UHD_COMMON_H */

gr-uhd/lib/gr_uhd_usrp_sink.cc

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 Free Software Foundation, Inc.
2+
* Copyright 2010-2012 Free Software Foundation, Inc.
33
*
44
* This file is part of GNU Radio
55
*
@@ -23,6 +23,7 @@
2323
#include <gr_io_signature.h>
2424
#include <stdexcept>
2525
#include <boost/make_shared.hpp>
26+
#include "gr_uhd_common.h"
2627

2728
static const pmt::pmt_t SOB_KEY = pmt::pmt_string_to_symbol("tx_sob");
2829
static const pmt::pmt_t EOB_KEY = pmt::pmt_string_to_symbol("tx_eob");
@@ -56,7 +57,9 @@ class uhd_usrp_sink_impl : public uhd_usrp_sink{
5657
gr_make_io_signature(0, 0, 0)
5758
),
5859
_stream_args(stream_args),
59-
_nchan(std::max<size_t>(1, stream_args.channels.size()))
60+
_nchan(std::max<size_t>(1, stream_args.channels.size())),
61+
_stream_now(_nchan == 1),
62+
_start_time_set(false)
6063
{
6164
if (stream_args.cpu_format == "fc32") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_FLOAT32);
6265
if (stream_args.cpu_format == "sc16") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_INT16);
@@ -381,6 +384,12 @@ class uhd_usrp_sink_impl : public uhd_usrp_sink{
381384
}
382385
}
383386

387+
void set_start_time(const uhd::time_spec_t &time){
388+
_start_time = time;
389+
_start_time_set = true;
390+
_stream_now = false;
391+
}
392+
384393
//Send an empty start-of-burst packet to begin streaming.
385394
//Set at a time in the near future to avoid late packets.
386395
bool start(void){
@@ -390,8 +399,14 @@ class uhd_usrp_sink_impl : public uhd_usrp_sink{
390399

391400
_metadata.start_of_burst = true;
392401
_metadata.end_of_burst = false;
393-
_metadata.has_time_spec = _nchan > 1;
394-
_metadata.time_spec = get_time_now() + uhd::time_spec_t(0.01);
402+
_metadata.has_time_spec = not _stream_now;
403+
if (_start_time_set){
404+
_start_time_set = false; //cleared for next run
405+
_metadata.time_spec = _start_time;
406+
}
407+
else{
408+
_metadata.time_spec = get_time_now() + uhd::time_spec_t(0.01);
409+
}
395410

396411
#ifdef GR_UHD_USE_STREAM_API
397412
_tx_stream->send(
@@ -432,9 +447,13 @@ class uhd_usrp_sink_impl : public uhd_usrp_sink{
432447
uhd::tx_streamer::sptr _tx_stream;
433448
#endif
434449
size_t _nchan;
450+
bool _stream_now;
435451
uhd::tx_metadata_t _metadata;
436452
double _sample_rate;
437453

454+
uhd::time_spec_t _start_time;
455+
bool _start_time_set;
456+
438457
//stream tags related stuff
439458
std::vector<gr_tag_t> _tags;
440459
};
@@ -465,6 +484,7 @@ boost::shared_ptr<uhd_usrp_sink> uhd_make_usrp_sink(
465484
const uhd::device_addr_t &device_addr,
466485
const uhd::stream_args_t &stream_args
467486
){
487+
gr_uhd_check_abi();
468488
return boost::shared_ptr<uhd_usrp_sink>(
469489
new uhd_usrp_sink_impl(device_addr, stream_args)
470490
);

gr-uhd/lib/gr_uhd_usrp_source.cc

+56-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 Free Software Foundation, Inc.
2+
* Copyright 2010-2012 Free Software Foundation, Inc.
33
*
44
* This file is part of GNU Radio
55
*
@@ -25,6 +25,7 @@
2525
#include <iostream>
2626
#include <boost/format.hpp>
2727
#include <boost/make_shared.hpp>
28+
#include "gr_uhd_common.h"
2829

2930
static const pmt::pmt_t TIME_KEY = pmt::pmt_string_to_symbol("rx_time");
3031

@@ -58,7 +59,8 @@ class uhd_usrp_source_impl : public uhd_usrp_source{
5859
_stream_args(stream_args),
5960
_nchan(std::max<size_t>(1, stream_args.channels.size())),
6061
_stream_now(_nchan == 1),
61-
_tag_now(false)
62+
_tag_now(false),
63+
_start_time_set(false)
6264
{
6365
if (stream_args.cpu_format == "fc32") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_FLOAT32);
6466
if (stream_args.cpu_format == "sc16") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_INT16);
@@ -371,6 +373,12 @@ class uhd_usrp_source_impl : public uhd_usrp_source{
371373
return num_samps;
372374
}
373375

376+
void set_start_time(const uhd::time_spec_t &time){
377+
_start_time = time;
378+
_start_time_set = true;
379+
_stream_now = false;
380+
}
381+
374382
bool start(void){
375383
#ifdef GR_UHD_USE_STREAM_API
376384
_rx_stream = _dev->get_rx_stream(_stream_args);
@@ -380,7 +388,13 @@ class uhd_usrp_source_impl : public uhd_usrp_source{
380388
static const double reasonable_delay = 0.1; //order of magnitude over RTT
381389
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
382390
stream_cmd.stream_now = _stream_now;
383-
stream_cmd.time_spec = get_time_now() + uhd::time_spec_t(reasonable_delay);
391+
if (_start_time_set){
392+
_start_time_set = false; //cleared for next run
393+
stream_cmd.time_spec = _start_time;
394+
}
395+
else{
396+
stream_cmd.time_spec = get_time_now() + uhd::time_spec_t(reasonable_delay);
397+
}
384398
_dev->issue_stream_cmd(stream_cmd);
385399
_tag_now = true;
386400
return true;
@@ -418,17 +432,48 @@ class uhd_usrp_source_impl : public uhd_usrp_source{
418432
}
419433

420434
std::vector<std::complex<float> > finite_acquisition(const size_t nsamps){
435+
if (_nchan != 1) throw std::runtime_error("finite_acquisition: usrp source has multiple channels, call finite_acquisition_v");
436+
return finite_acquisition_v(nsamps).front();
437+
}
438+
439+
std::vector<std::vector<std::complex<float> > > finite_acquisition_v(const size_t nsamps){
421440
#ifdef GR_UHD_USE_STREAM_API
441+
442+
//kludgy way to ensure rx streamer exsists
443+
if (!_rx_stream){
444+
this->start();
445+
this->stop();
446+
}
447+
448+
//flush so there is no queued-up data
449+
this->flush();
450+
451+
//create a multi-dimensional container to hold an array of sample buffers
452+
std::vector<std::vector<std::complex<float> > > samps(_nchan, std::vector<std::complex<float> >(nsamps));
453+
454+
//load the void* vector of buffer pointers
455+
std::vector<void *> buffs(_nchan);
456+
for (size_t i = 0; i < _nchan; i++){
457+
buffs[i] = &samps[i].front();
458+
}
459+
460+
//tell the device to stream a finite amount
422461
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
423462
cmd.num_samps = nsamps;
424-
cmd.stream_now = true;
463+
cmd.stream_now = _stream_now;
464+
static const double reasonable_delay = 0.1; //order of magnitude over RTT
465+
cmd.time_spec = get_time_now() + uhd::time_spec_t(reasonable_delay);
425466
_dev->issue_stream_cmd(cmd);
426467

427-
std::vector<std::complex<float> > samps(nsamps);
468+
//receive samples until timeout
428469
const size_t actual_num_samps = _rx_stream->recv(
429-
&samps.front(), nsamps, _metadata, 0.1
470+
buffs, nsamps, _metadata, 1.0
430471
);
431-
samps.resize(actual_num_samps);
472+
473+
//resize the resulting sample buffers
474+
for (size_t i = 0; i < _nchan; i++){
475+
samps[i].resize(actual_num_samps);
476+
}
432477

433478
return samps;
434479
#else
@@ -448,6 +493,9 @@ class uhd_usrp_source_impl : public uhd_usrp_source{
448493
bool _stream_now, _tag_now;
449494
uhd::rx_metadata_t _metadata;
450495
pmt::pmt_t _id;
496+
497+
uhd::time_spec_t _start_time;
498+
bool _start_time_set;
451499
};
452500

453501

@@ -477,6 +525,7 @@ boost::shared_ptr<uhd_usrp_source> uhd_make_usrp_source(
477525
const uhd::device_addr_t &device_addr,
478526
const uhd::stream_args_t &stream_args
479527
){
528+
gr_uhd_check_abi();
480529
return boost::shared_ptr<uhd_usrp_source>(
481530
new uhd_usrp_source_impl(device_addr, stream_args)
482531
);

gr-uhd/swig/__init__.py

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class device_addr_t(uhd_swig.device_addr_t, str):
5555
def __new__(self, *args): return str.__new__(self)
5656
def __getitem__(self, key): return self.get(key)
5757
def __setitem__(self, key, val): self.set(key, val)
58+
def __init__(self, *args, **kwargs):
59+
super(device_addr_t, self).__init__(*args)
60+
if args and isinstance(args[0], device_addr_t):
61+
for key in args[0].keys(): self[key] = args[0][key]
5862
setattr(uhd_swig, 'device_addr_t', device_addr_t)
5963

6064
#make the streamer args take **kwargs on init

0 commit comments

Comments
 (0)