aboutsummaryrefslogtreecommitdiffstats
path: root/host/examples
diff options
context:
space:
mode:
Diffstat (limited to 'host/examples')
-rw-r--r--host/examples/benchmark_rate.cpp52
-rw-r--r--host/examples/init_usrp/CMakeLists.txt2
-rw-r--r--host/examples/tx_bursts.cpp40
-rw-r--r--host/examples/tx_samples_c.c21
-rw-r--r--host/examples/tx_waveforms.cpp30
5 files changed, 115 insertions, 30 deletions
diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp
index 0f01da035..b024c3a20 100644
--- a/host/examples/benchmark_rate.cpp
+++ b/host/examples/benchmark_rate.cpp
@@ -47,6 +47,8 @@ unsigned long long num_rx_samps = 0;
unsigned long long num_tx_samps = 0;
unsigned long long num_dropped_samps = 0;
unsigned long long num_seq_errors = 0;
+unsigned long long num_late_commands = 0;
+unsigned long long num_timeouts = 0;
/***********************************************************************
* Benchmark RX Rate
@@ -84,10 +86,12 @@ void benchmark_rx_rate(
const float burst_pkt_time = std::max(0.100, (2 * max_samps_per_packet/rate));
float recv_timeout = burst_pkt_time + INIT_DELAY;
+ bool stop_called = false;
while (true) {
- //if (burst_timer_elapsed.load(boost::memory_order_relaxed)) {
- if (burst_timer_elapsed) {
+ //if (burst_timer_elapsed.load(boost::memory_order_relaxed) and not stop_called) {
+ if (burst_timer_elapsed and not stop_called) {
rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+ stop_called = true;
}
if (random_nsamps) {
cmd.num_samps = rand() % max_samps_per_packet;
@@ -110,6 +114,10 @@ void benchmark_rx_rate(
had_an_overflow = false;
num_dropped_samps += (md.time_spec - last_time).to_ticks(rate);
}
+ if ((burst_timer_elapsed or stop_called) and md.end_of_burst)
+ {
+ return;
+ }
break;
// ERROR_CODE_OVERFLOW can indicate overflow or sequence error
@@ -121,12 +129,23 @@ void benchmark_rx_rate(
num_overflows++;
break;
+ case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
+ std::cerr << "Receiver error: " << md.strerror() << ", restart streaming..."<< std::endl;
+ num_late_commands++;
+ // Radio core will be in the idle state. Issue stream command to restart streaming.
+ cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
+ cmd.stream_now = (buffs.size() == 1);
+ rx_stream->issue_stream_cmd(cmd);
+ break;
+
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
- // If we stopped the streamer, then we expect this at some point
- //if (burst_timer_elapsed.load(boost::memory_order_relaxed)) {
if (burst_timer_elapsed) {
return;
}
+ std::cerr << "Receiver error: " << md.strerror() << ", continuing..." << std::endl;
+ num_timeouts++;
+ break;
+
// Otherwise, it's an error
default:
std::cerr << "Receiver error: " << md.strerror() << std::endl;
@@ -243,6 +262,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args;
+ std::string rx_subdev, tx_subdev;
double duration;
double rx_rate, tx_rate;
std::string rx_otw, tx_otw;
@@ -258,6 +278,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
("duration", po::value<double>(&duration)->default_value(10.0), "duration for the test in seconds")
+ ("rx_subdev", po::value<std::string>(&rx_subdev), "specify the device subdev for RX")
+ ("tx_subdev", po::value<std::string>(&tx_subdev), "specify the device subdev for TX")
("rx_rate", po::value<double>(&rx_rate), "specify to perform a RX rate test (sps)")
("tx_rate", po::value<double>(&tx_rate), "specify to perform a TX rate test (sps)")
("rx_otw", po::value<std::string>(&rx_otw)->default_value("sc16"), "specify the over-the-wire sample mode for RX")
@@ -310,6 +332,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
+
+ //always select the subdevice first, the channel mapping affects the other settings
+ if (vm.count("rx_subdev")) {
+ usrp->set_rx_subdev_spec(rx_subdev);
+ }
+ if (vm.count("tx_subdev")) {
+ usrp->set_tx_subdev_spec(tx_subdev);
+ }
+
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
int num_mboards = usrp->get_num_mboards();
@@ -406,7 +437,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//sleep for the required duration
const long secs = long(duration);
const long usecs = long((duration - secs)*1e6);
- boost::this_thread::sleep(boost::posix_time::seconds(secs) + boost::posix_time::microseconds(usecs));
+ boost::this_thread::sleep(boost::posix_time::seconds(secs)
+ + boost::posix_time::microseconds(usecs)
+ + boost::posix_time::milliseconds( (channel_nums.size() == 1) ? 0 : (INIT_DELAY * 1000))
+ );
//interrupt and join the threads
//burst_timer_elapsed.store(true, boost::memory_order_relaxed);
@@ -422,7 +456,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
" Num transmitted samples: %u\n"
" Num sequence errors: %u\n"
" Num underflows detected: %u\n"
- ) % num_rx_samps % num_dropped_samps % num_overflows % num_tx_samps % num_seq_errors % num_underflows << std::endl;
+ " Num late commands: %u\n"
+ " Num timeouts: %u\n"
+ ) % num_rx_samps % num_dropped_samps
+ % num_overflows % num_tx_samps
+ % num_seq_errors % num_underflows
+ % num_late_commands % num_timeouts
+ << std::endl;
//finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
diff --git a/host/examples/init_usrp/CMakeLists.txt b/host/examples/init_usrp/CMakeLists.txt
index 8705b4a8d..4ce51125f 100644
--- a/host/examples/init_usrp/CMakeLists.txt
+++ b/host/examples/init_usrp/CMakeLists.txt
@@ -59,7 +59,7 @@ SET(CMAKE_BUILD_TYPE "Release")
MESSAGE(STATUS "******************************************************************************")
MESSAGE(STATUS "* NOTE: When building your own app, you probably need all kinds of different ")
MESSAGE(STATUS "* compiler flags. This is just an example, so it's unlikely these settings ")
-MESSAGE(STATUS "* exactly matchh what you require. Make sure to double-check compiler and ")
+MESSAGE(STATUS "* exactly match what you require. Make sure to double-check compiler and ")
MESSAGE(STATUS "* linker flags to make sure your specific requirements are included. ")
MESSAGE(STATUS "******************************************************************************")
diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp
index bb71d4581..5ee00d5cd 100644
--- a/host/examples/tx_bursts.cpp
+++ b/host/examples/tx_bursts.cpp
@@ -142,7 +142,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
size_t num_acc_samps = 0; //number of accumulated samples
while(num_acc_samps < total_num_samps){
- size_t samps_to_send = std::min(total_num_samps - num_acc_samps, spb);
+ size_t samps_to_send = total_num_samps - num_acc_samps;
+ if (samps_to_send > spb)
+ {
+ samps_to_send = spb;
+ } else {
+ md.end_of_burst = true;
+ }
//send a single packet
size_t num_tx_samps = tx_stream->send(
@@ -152,25 +158,37 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
md.has_time_spec = false;
md.start_of_burst = false;
- if (num_tx_samps < samps_to_send) std::cerr << "Send timeout..." << std::endl;
- if(verbose) std::cout << boost::format("Sent packet: %u samples") % num_tx_samps << std::endl;
+ if (num_tx_samps < samps_to_send)
+ {
+ std::cerr << "Send timeout..." << std::endl;
+ if (stop_signal_called)
+ {
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if(verbose)
+ {
+ std::cout << boost::format("Sent packet: %u samples") % num_tx_samps << std::endl;
+ }
num_acc_samps += num_tx_samps;
}
- md.end_of_burst = true;
- tx_stream->send(buffs, 0, md, timeout);
-
time_to_send += rep_rate;
std::cout << std::endl << "Waiting for async burst ACK... " << std::flush;
uhd::async_metadata_t async_md;
- bool got_async_burst_ack = false;
- //loop through all messages for the ACK packet (may have underflow messages in queue)
- while (not got_async_burst_ack and tx_stream->recv_async_msg(async_md, seconds_in_future)){
- got_async_burst_ack = (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK);
+ size_t acks = 0;
+ //loop through all messages for the ACK packets (may have underflow messages in queue)
+ while (acks < channel_nums.size() and tx_stream->recv_async_msg(async_md, seconds_in_future))
+ {
+ if (async_md.event_code == uhd::async_metadata_t::EVENT_CODE_BURST_ACK)
+ {
+ acks++;
+ }
}
- std::cout << (got_async_burst_ack? "success" : "fail") << std::endl;
+ std::cout << (acks == channel_nums.size() ? "success" : "fail") << std::endl;
} while (not stop_signal_called and repeat);
//finished
diff --git a/host/examples/tx_samples_c.c b/host/examples/tx_samples_c.c
index c052d80ed..3c3fcc8fe 100644
--- a/host/examples/tx_samples_c.c
+++ b/host/examples/tx_samples_c.c
@@ -21,6 +21,7 @@
#include <math.h>
#include <signal.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -39,6 +40,7 @@ void print_help(void){
" -f (frequency in Hz)\n"
" -r (sample rate in Hz)\n"
" -g (gain)\n"
+ " -n (number of samples to transmit)\n"
" -v (enable verbose prints)\n"
" -h (print this help message)\n");
}
@@ -57,12 +59,13 @@ int main(int argc, char* argv[]){
double gain = 0;
char* device_args = "";
size_t channel = 0;
+ uint64_t total_num_samps = 0;
bool verbose = false;
int return_code = EXIT_SUCCESS;
char error_string[512];
// Process options
- while((option = getopt(argc, argv, "a:f:r:g:vh")) != -1){
+ while((option = getopt(argc, argv, "a:f:r:g:n:vh")) != -1){
switch(option){
case 'a':
device_args = strdup(optarg);
@@ -80,6 +83,10 @@ int main(int argc, char* argv[]){
gain = atof(optarg);
break;
+ case 'n':
+ total_num_samps = atoll(optarg);
+ break;
+
case 'v':
verbose = true;
break;
@@ -198,11 +205,19 @@ int main(int argc, char* argv[]){
fprintf(stderr, "Press Ctrl+C to stop streaming...\n");
// Actual streaming
- size_t num_samps_sent = 0;
- while(!stop_signal_called){
+ uint64_t num_acc_samps = 0;
+ uint64_t num_samps_sent = 0;
+
+ while(1) {
+ if (stop_signal_called) break;
+ if (total_num_samps > 0 && num_acc_samps >= total_num_samps) break;
+
EXECUTE_OR_GOTO(free_tx_streamer,
uhd_tx_streamer_send(tx_streamer, buffs_ptr, samps_per_buff, &md, 0.1, &num_samps_sent)
)
+
+ num_acc_samps += num_samps_sent;
+
if(verbose){
fprintf(stderr, "Sent %zu samples\n", num_samps_sent);
}
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp
index af8f92607..b2a8f944c 100644
--- a/host/examples/tx_waveforms.cpp
+++ b/host/examples/tx_waveforms.cpp
@@ -28,6 +28,7 @@
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
+#include <stdint.h>
#include <iostream>
#include <csignal>
@@ -47,7 +48,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//variables to be set by po
std::string args, wave_type, ant, subdev, ref, pps, otw, channel_list;
- size_t spb;
+ uint64_t total_num_samps, spb;
double rate, freq, gain, wave_freq, bw;
float ampl;
@@ -56,7 +57,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
- ("spb", po::value<size_t>(&spb)->default_value(0), "samples per buffer, 0 for default")
+ ("spb", po::value<uint64_t>(&spb)->default_value(0), "samples per buffer, 0 for default")
+ ("nsamps", po::value<uint64_t>(&total_num_samps)->default_value(0), "total number of samples to transmit")
("rate", po::value<double>(&rate), "rate of outgoing samples")
("freq", po::value<double>(&freq), "RF center frequency in Hz")
("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of the waveform [0 to 0.7]")
@@ -211,20 +213,22 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//Check Ref and LO Lock detect
std::vector<std::string> sensor_names;
- sensor_names = usrp->get_tx_sensor_names(0);
+ const size_t tx_sensor_chan = channel_list.empty() ? 0 : boost::lexical_cast<size_t>(channel_list[0]);
+ sensor_names = usrp->get_tx_sensor_names(tx_sensor_chan);
if (std::find(sensor_names.begin(), sensor_names.end(), "lo_locked") != sensor_names.end()) {
- uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked",0);
+ uhd::sensor_value_t lo_locked = usrp->get_tx_sensor("lo_locked", tx_sensor_chan);
std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string() << std::endl;
UHD_ASSERT_THROW(lo_locked.to_bool());
}
- sensor_names = usrp->get_mboard_sensor_names(0);
+ const size_t mboard_sensor_idx = 0;
+ sensor_names = usrp->get_mboard_sensor_names(mboard_sensor_idx);
if ((ref == "mimo") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) {
- uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0);
+ uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked", mboard_sensor_idx);
std::cout << boost::format("Checking TX: %s ...") % mimo_locked.to_pp_string() << std::endl;
UHD_ASSERT_THROW(mimo_locked.to_bool());
}
if ((ref == "external") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) {
- uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0);
+ uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked", mboard_sensor_idx);
std::cout << boost::format("Checking TX: %s ...") % ref_locked.to_pp_string() << std::endl;
UHD_ASSERT_THROW(ref_locked.to_bool());
}
@@ -241,14 +245,22 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
md.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.1);
//send data until the signal handler gets called
- while(not stop_signal_called){
+ //or if we accumulate the number of samples specified (unless it's 0)
+ uint64_t num_acc_samps = 0;
+ while(true){
+
+ if (stop_signal_called) break;
+ if (total_num_samps > 0 and num_acc_samps >= total_num_samps) break;
+
//fill the buffer with the waveform
for (size_t n = 0; n < buff.size(); n++){
buff[n] = wave_table(index += step);
}
//send the entire contents of the buffer
- tx_stream->send(buffs, buff.size(), md);
+ num_acc_samps += tx_stream->send(
+ buffs, buff.size(), md
+ );
md.start_of_burst = false;
md.has_time_spec = false;