Hi, We have an X300 with LFRX on slot A, and LFTX on both slots (uhd_usrp_probe output attached).
The idea was to do signal processing on two synchronously sampled channels from the same LFRX board, using a custom RFNoC OOT. So something along the lines of: Radio0,0 LFRX(A) -> DDC0,0 -> |in_0 OOT-block out | -> DUC1,0 -> LFTX(A) Radio1,0 Radio0,1 LFRX(B) -> DDC0,1 -> |in_1 | I tried to test dual-channel processing with RFNoC blocks shipped with UHD, so I built a custom FPGA-bitstream with various blocks connected to individual stream points (as listed in the uhd_usrp_probe output, yml file is also attached). So the first obvious test was to loopback two RX channel to two TX channels, like this: Radio0 LFRX(A) -> DDC0,0 -> DUC1,0 -> LFTX(A) Radio1 Radio0 LFRX(B) -> DDC0,1 -> DUC0,0 -> LFTX(A) Radio0 First channel goes from Radio0 to Radio1, and it seems to work. But I can't get the second channel to work. So is it even possible to loop back data from RX to TX on the same radio? Each radio instance has only one TX DSP chain, as I understood, so I had to use the TX chain on the Radio0 side, too. The custom FPGA image has separate SEPs for each DDC and DUC, so traffic should be correctly routed through the CHDR crossbar. Please see the attached minimal C++ example (loopback_test.cpp, modeled after the loopback example shipped with UHD source code). Active connections formed in the test program are like so: 0/Radio#0:0==>0/DDC#0:0 0/Radio#0:1==>0/DDC#0:1 0/DDC#0:0-->0/DUC#1:0 0/DDC#0:1-->0/DUC#0:0 0/DUC#1:0==>0/Radio#1:0 0/DUC#0:0==>0/Radio#0:0 Graph is committed without problems. The program outputs something like: Issuing start stream cmd... OWait... U Test signal propagates fine from Radio0 to Radio1, but the second one does not seem to work. The overflow indicator "O" always appears when trying use the second channel. In an attempt to eliminate the possibility of loopback problems, I also tried the addsub -block with the subtract-output statically connected to a null sink. The test program (addsub.cpp) does not seem to stream anything, and outputs the following warnings: [WARNING] [RFNOC::GRAPH] One or more blocks timed out during flush! O[WARNING] [RFNOC::GRAPH::DETAIL] Cannot forward action rx_event from 0/Radio#0:OUTPUT_EDGE:1, no neighbour found! O[WARNING] [RFNOC::GRAPH::DETAIL] Cannot forward action rx_event from 0/Radio#0:OUTPUT_EDGE:0, no neighbour found! Active connections for the addsub-test are: 0/Radio#0:0==>0/DDC#0:0 0/Radio#0:1==>0/DDC#0:1 0/DDC#0:0-->0/AddSub#0:0 0/DDC#0:1-->0/AddSub#0:1 0/AddSub#0:0-->0/DUC#1:0 0/AddSub#0:1==>0/NullSrcSink#0:0 0/DUC#1:0==>0/Radio#1:0 So am I missing something trivial here? I guess there are at least three things that could be wrong here: - How to correctly configure synchronous dual-channel sampling? - Is it possible to loop back data from Radio0 RX to Radio0 TX through CHDR crossbar? - How to correctly configure and use the addsub-block? Is it necessary to issue stream commands to both RX radio channels, like so (with identical time spec): rx_radio_ctrl->issue_stream_cmd(stream_cmd, 0); rx_radio_ctrl->issue_stream_cmd(stream_cmd, 1); One more thing to note: using Gnuradio UHD/RFNoC interface (major version 3.10) to stream 2 channels to host though DDCs and RX streamers works just fine. Thank you in advance. With best regards, Kalle Hanhijärvi
x300_dualchannel.yml
Description: x300_dualchannel.yml
$ uhd_usrp_probe [INFO] [UHD] linux; GNU C++ version 9.4.0; Boost_107100; DPDK_19.11; UHD_4.4.0.0-33-g4a77791c [INFO] [X300] X300 initialization sequence... [INFO] [X300] Maximum frame size: 1472 bytes. [INFO] [X300] Radio 1x clock: 200 MHz [INFO] [0/FIR#0] Setting default MTU forward policy. [INFO] [0/FIR#1] Setting default MTU forward policy. _____________________________________________________ / | Device: X-Series Device | _____________________________________________________ | / | | Mboard: X300 | | revision: 12 | | revision_compat: 7 | | product: 30817 | | mac-addr0: 00:80:2f:37:db:e5 | | mac-addr1: 00:80:2f:37:db:e6 | | gateway: 192.168.10.1 | | ip-addr0: 192.168.10.2 | | subnet0: 255.255.255.0 | | ip-addr1: 192.168.20.2 | | subnet1: 255.255.255.0 | | ip-addr2: 192.168.30.2 | | subnet2: 255.255.255.0 | | ip-addr3: 192.168.40.2 | | subnet3: 255.255.255.0 | | serial: 328C972 | | FW Version: 6.1 | | FPGA Version: 39.2 | | FPGA git hash: fffffff-dirty | | RFNoC capable: Yes | | | | Time sources: internal, external, gpsdo | | Clock sources: internal, external, gpsdo | | Sensors: ref_locked | _____________________________________________________ | / | | RFNoC blocks on this device: | | | | * 0/AddSub#0 | | * 0/DDC#0 | | * 0/DDC#1 | | * 0/DUC#0 | | * 0/DUC#1 | | * 0/FIR#0 | | * 0/FIR#1 | | * 0/NullSrcSink#0 | | * 0/Radio#0 | | * 0/Radio#1 | _____________________________________________________ | / | | Static connections on this device: | | | | * 0/SEP#3:0==>0/DUC#0:0 | | * 0/DUC#0:0==>0/Radio#0:0 | | * 0/Radio#0:0==>0/DDC#0:0 | | * 0/DDC#0:0==>0/SEP#0:0 | | * 0/Radio#0:1==>0/DDC#0:1 | | * 0/DDC#0:1==>0/SEP#1:0 | | * 0/SEP#2:0==>0/DUC#1:0 | | * 0/DUC#1:0==>0/Radio#1:0 | | * 0/Radio#1:0==>0/DDC#1:0 | | * 0/DDC#1:0==>0/SEP#2:0 | | * 0/SEP#4:0==>0/FIR#0:0 | | * 0/SEP#5:0==>0/FIR#1:0 | | * 0/FIR#0:0==>0/SEP#4:0 | | * 0/FIR#1:0==>0/SEP#5:0 | | * 0/SEP#6:0==>0/AddSub#0:0 | | * 0/SEP#7:0==>0/AddSub#0:1 | | * 0/AddSub#0:0==>0/SEP#8:0 | | * 0/AddSub#0:1==>0/NullSrcSink#0:0 | _____________________________________________________ | / | | TX Dboard: 0/Radio#0 | | ID: LF TX (0x630e) | | Serial: 3253F17 | | _____________________________________________________ | | / | | | TX Frontend: 0 | | | Name: LFTX (0) | | | Antennas: AB, BA, A, B | | | Sensors: | | | Freq range: -32.000 to 32.000 MHz | | | Gain Elements: None | | | Bandwidth range: 64000000.0 to 64000000.0 step 0.0 Hz | | | Connection Type: IQ | | | Uses LO offset: No | _____________________________________________________ | / | | RX Dboard: 0/Radio#0 | | ID: LF RX (0x630f) | | Serial: 30DDF1D | | _____________________________________________________ | | / | | | RX Frontend: 0 | | | Name: LFRX (0) | | | Antennas: AB, BA, A, B | | | Sensors: | | | Freq range: -32.000 to 32.000 MHz | | | Gain Elements: None | | | Bandwidth range: 64000000.0 to 64000000.0 step 0.0 Hz | | | Connection Type: IQ | | | Uses LO offset: No | | _____________________________________________________ | | / | | | RX Frontend: 1 | | | Name: LFRX (1) | | | Antennas: AB, BA, A, B | | | Sensors: | | | Freq range: -32.000 to 32.000 MHz | | | Gain Elements: None | | | Bandwidth range: 64000000.0 to 64000000.0 step 0.0 Hz | | | Connection Type: IQ | | | Uses LO offset: No | _____________________________________________________ | / | | TX Dboard: 0/Radio#1 | | ID: LF TX (0x630e) | | Serial: 324FED4 | | _____________________________________________________ | | / | | | TX Frontend: 0 | | | Name: LFTX (0) | | | Antennas: AB, BA, A, B | | | Sensors: | | | Freq range: -32.000 to 32.000 MHz | | | Gain Elements: None | | | Bandwidth range: 64000000.0 to 64000000.0 step 0.0 Hz | | | Connection Type: IQ | | | Uses LO offset: No | _____________________________________________________ | / | | RX Dboard: 0/Radio#1 | | _____________________________________________________ | | / | | | RX Frontend: 0 | | | Name: Unknown (0xffff) - 0 | | | Antennas: | | | Sensors: | | | Freq range: 0.000 to 0.000 MHz | | | Gain Elements: None | | | Bandwidth range: 0.0 to 0.0 step 0.0 Hz | | | Connection Type: IQ | | | Uses LO offset: No
#include <uhd/rfnoc/block_id.hpp> #include <uhd/rfnoc/mb_controller.hpp> #include <uhd/rfnoc/radio_control.hpp> #include <uhd/rfnoc_graph.hpp> #include <uhd/types/tune_request.hpp> #include <uhd/utils/graph_utils.hpp> #include <uhd/utils/math.hpp> #include <uhd/utils/safe_main.hpp> #include <boost/format.hpp> #include <chrono> #include <csignal> #include <iostream> #include <thread> using uhd::rfnoc::radio_control; using namespace std::chrono_literals; /**************************************************************************** * SIGINT handling ***************************************************************************/ static bool stop_signal_called = false; void sig_int_handler(int) { stop_signal_called = true; } /**************************************************************************** * main ***************************************************************************/ int UHD_SAFE_MAIN(int argc, char* argv[]) { std::string args, rx_ant, tx_ant, rx_blockid, tx_blockid, ref, pps; size_t total_num_samps, spp, rx_chan, tx_chan; double rate, rx_freq, tx_freq, rx_bw, tx_bw, total_time, setup_time; bool rx_timestamps; rate = 200e6; spp = 0; rx_freq = 0.0; tx_freq = 0.0; rx_bw = 32e6; tx_bw = 32e6; rx_chan = 0; tx_chan = 0; total_num_samps = 0; total_time = 0.0; rx_blockid = "0/Radio#0"; tx_blockid = "0/Radio#1"; // Set timestamps on RX rx_timestamps = false; // Setup time setup_time = 0.1; ref = "internal"; pps = "internal"; /************************************************************************ * Create device and block controls ***********************************************************************/ std::cout << std::endl; std::cout << boost::format("Creating the RFNoC graph with args: %s...") % args << std::endl; uhd::rfnoc::rfnoc_graph::sptr graph = uhd::rfnoc::rfnoc_graph::make(args); // Create handles for radio objects uhd::rfnoc::block_id_t rx_radio_ctrl_id(rx_blockid); uhd::rfnoc::block_id_t tx_radio_ctrl_id(tx_blockid); // This next line will fail if the radio is not actually available uhd::rfnoc::radio_control::sptr rx_radio_ctrl = graph->get_block<uhd::rfnoc::radio_control>(rx_radio_ctrl_id); uhd::rfnoc::radio_control::sptr tx_radio_ctrl = graph->get_block<uhd::rfnoc::radio_control>(tx_radio_ctrl_id); std::cout << "Using RX radio " << rx_radio_ctrl_id << ", channel " << rx_chan << std::endl; std::cout << "Using TX radio " << tx_radio_ctrl_id << ", channel " << tx_chan << std::endl; size_t rx_mb_idx = rx_radio_ctrl_id.get_device_no(); /************************************************************************ * Set up radio ***********************************************************************/ // Only forward properties once per block in the chain. In the case of // looping back to a single radio block, skip property propagation after // traversing back to the starting point of the chain. const bool skip_pp = rx_radio_ctrl_id == tx_radio_ctrl_id; std::cout << "skip_pp: " << skip_pp << std::endl; // Connect manually uhd::rfnoc::block_id_t rx_radio_ddc_id("0/DDC#0"); uhd::rfnoc::block_id_t rx_radio_duc_id("0/DUC#0"); uhd::rfnoc::block_id_t tx_radio_duc_id("0/DUC#1"); uhd::rfnoc::block_id_t addsub_id("0/AddSub#0"); uhd::rfnoc::block_id_t null_id("0/NullSrcSink#0"); // RX radio channels to DDCs graph->connect(rx_blockid, 0, rx_radio_ddc_id, 0, false); graph->connect(rx_blockid, 1, rx_radio_ddc_id, 1, false); // DDCs to addsub graph->connect(rx_radio_ddc_id, 0, addsub_id, 0, false); graph->connect(rx_radio_ddc_id, 1, addsub_id, 1, false); // Addsub to DUC and null sink graph->connect(addsub_id, 0, tx_radio_duc_id, 0, false); graph->connect(addsub_id, 1, null_id, 0, false); // DUCs to radios graph->connect(tx_radio_duc_id, 0, tx_radio_ctrl_id, 0, false); graph->commit(); std::vector<uhd::rfnoc::graph_edge_t> active_connections = graph->enumerate_active_connections(); std::vector<uhd::rfnoc::graph_edge_t>::iterator iter = active_connections.begin(); // Print active connections for(iter; iter < active_connections.end(); iter++) { std::cout << (*iter).to_string() << std::endl;; } rx_radio_ctrl->enable_rx_timestamps(rx_timestamps, rx_chan); // Set time and clock reference for (size_t i = 0; i < graph->get_num_mboards(); ++i) { graph->get_mb_controller(i)->set_clock_source(ref); } // Lock mboard clocks for (size_t i = 0; i < graph->get_num_mboards(); ++i) { graph->get_mb_controller(i)->set_time_source(pps); } rate = rx_radio_ctrl->set_rate(rate); // set the sample rate std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate / 1e6) << std::endl; rate = rx_radio_ctrl->set_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (rate / 1e6) << std::endl << std::endl; // set the center frequency std::cout << boost::format("Setting RX Freq: %f MHz...") % (rx_freq / 1e6) << std::endl; rx_radio_ctrl->set_rx_frequency(rx_freq, rx_chan); std::cout << boost::format("Actual RX Freq: %f MHz...") % (rx_radio_ctrl->get_rx_frequency(rx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Freq: %f MHz...") % (tx_freq / 1e6) << std::endl; tx_radio_ctrl->set_tx_frequency(tx_freq, tx_chan); std::cout << boost::format("Actual TX Freq: %f MHz...") % (tx_radio_ctrl->get_tx_frequency(tx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % (rx_bw / 1e6) << std::endl; rx_radio_ctrl->set_rx_bandwidth(rx_bw, rx_chan); std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % (rx_radio_ctrl->get_rx_bandwidth(rx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % (tx_bw / 1e6) << std::endl; tx_radio_ctrl->set_tx_bandwidth(tx_bw, tx_chan); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % (tx_radio_ctrl->get_tx_bandwidth(tx_chan) / 1e6) << std::endl << std::endl; // Antennas rx_radio_ctrl->set_rx_antenna("A", 0); rx_radio_ctrl->set_rx_antenna("B", 1); tx_radio_ctrl->set_tx_antenna("A", 0); rx_radio_ctrl->set_tx_antenna("A", 0); std::cout << "Setting samples per packet to: " << spp << std::endl; rx_radio_ctrl->set_property<int>("spp", spp, 0); spp = rx_radio_ctrl->get_property<int>("spp", 0); std::cout << "Actual samples per packet = " << spp << std::endl; // Allow for some setup time std::this_thread::sleep_for(1s * setup_time); // Arm SIGINT handler std::signal(SIGINT, &sig_int_handler); // Calculate timeout and set timers // We just need to check is nsamps was set, otherwise we'll use the duration if (total_num_samps > 0) { total_time = total_num_samps / rate; std::cout << boost::format("Expected streaming time: %.3f") % total_time << std::endl; } // Start streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); stream_cmd.num_samps = size_t(total_num_samps); stream_cmd.stream_now = false; stream_cmd.time_spec = graph->get_mb_controller(rx_mb_idx)->get_timekeeper(rx_mb_idx)->get_time_now() + setup_time; std::cout << "Issuing start stream cmd..." << std::endl; // Are two stream commands required for 2 channel RX? rx_radio_ctrl->issue_stream_cmd(stream_cmd, 0); rx_radio_ctrl->issue_stream_cmd(stream_cmd, 1); std::this_thread::sleep_for(1s * setup_time); std::cout << "Wait..." << std::endl; // Wait until we can exit uhd::time_spec_t elapsed_time = 0.0; while (not stop_signal_called) { std::this_thread::sleep_for(100ms); if (total_time > 0.0) { elapsed_time += 0.1; if (elapsed_time > total_time) { break; } } } // Stop radio stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; std::cout << "Issuing stop stream cmd..." << std::endl; rx_radio_ctrl->issue_stream_cmd(stream_cmd, rx_chan); std::cout << "Done" << std::endl; // Allow for the samples and ACKs to propagate std::this_thread::sleep_for(100ms); return EXIT_SUCCESS; }
#include <uhd/rfnoc/block_id.hpp> #include <uhd/rfnoc/mb_controller.hpp> #include <uhd/rfnoc/radio_control.hpp> #include <uhd/rfnoc_graph.hpp> #include <uhd/types/tune_request.hpp> #include <uhd/utils/graph_utils.hpp> #include <uhd/utils/math.hpp> #include <uhd/utils/safe_main.hpp> #include <boost/format.hpp> #include <chrono> #include <csignal> #include <iostream> #include <thread> using uhd::rfnoc::radio_control; using namespace std::chrono_literals; /**************************************************************************** * SIGINT handling ***************************************************************************/ static bool stop_signal_called = false; void sig_int_handler(int) { stop_signal_called = true; } /**************************************************************************** * main ***************************************************************************/ int UHD_SAFE_MAIN(int argc, char* argv[]) { std::string args, rx_ant, tx_ant, rx_blockid, tx_blockid, ref, pps; size_t total_num_samps, spp, rx_chan, tx_chan; double rate, rx_freq, tx_freq, rx_bw, tx_bw, total_time, setup_time; bool rx_timestamps; rate = 200e6; spp = 0; rx_freq = 0.0; tx_freq = 0.0; rx_bw = 32e6; tx_bw = 32e6; rx_chan = 0; tx_chan = 0; total_num_samps = 0; total_time = 0.0; rx_blockid = "0/Radio#0"; tx_blockid = "0/Radio#1"; // Set timestamps on RX rx_timestamps = false; // Setup time setup_time = 0.1; ref = "internal"; pps = "internal"; /************************************************************************ * Create device and block controls ***********************************************************************/ std::cout << std::endl; std::cout << boost::format("Creating the RFNoC graph with args: %s...") % args << std::endl; uhd::rfnoc::rfnoc_graph::sptr graph = uhd::rfnoc::rfnoc_graph::make(args); // Create handles for radio objects uhd::rfnoc::block_id_t rx_radio_ctrl_id(rx_blockid); uhd::rfnoc::block_id_t tx_radio_ctrl_id(tx_blockid); // This next line will fail if the radio is not actually available uhd::rfnoc::radio_control::sptr rx_radio_ctrl = graph->get_block<uhd::rfnoc::radio_control>(rx_radio_ctrl_id); uhd::rfnoc::radio_control::sptr tx_radio_ctrl = graph->get_block<uhd::rfnoc::radio_control>(tx_radio_ctrl_id); std::cout << "Using RX radio " << rx_radio_ctrl_id << ", channel " << rx_chan << std::endl; std::cout << "Using TX radio " << tx_radio_ctrl_id << ", channel " << tx_chan << std::endl; size_t rx_mb_idx = rx_radio_ctrl_id.get_device_no(); /************************************************************************ * Set up radio ***********************************************************************/ // Only forward properties once per block in the chain. In the case of // looping back to a single radio block, skip property propagation after // traversing back to the starting point of the chain. const bool skip_pp = rx_radio_ctrl_id == tx_radio_ctrl_id; std::cout << "skip_pp: " << skip_pp << std::endl; // Connect manually uhd::rfnoc::block_id_t rx_radio_ddc_id("0/DDC#0"); uhd::rfnoc::block_id_t rx_radio_duc_id("0/DUC#0"); uhd::rfnoc::block_id_t tx_radio_duc_id("0/DUC#1"); // RX radio channels to DDCs graph->connect(rx_blockid, 0, rx_radio_ddc_id, 0, false); graph->connect(rx_blockid, 1, rx_radio_ddc_id, 1, false); // DDCs to DUCs graph->connect(rx_radio_ddc_id, 0, tx_radio_duc_id, 0, false); graph->connect(rx_radio_ddc_id, 1, rx_radio_duc_id, 0, false); // DUCs to radios graph->connect(tx_radio_duc_id, 0, tx_radio_ctrl_id, 0, false); graph->connect(rx_radio_duc_id, 0, rx_radio_ctrl_id, 0, true); graph->commit(); std::vector<uhd::rfnoc::graph_edge_t> active_connections = graph->enumerate_active_connections(); std::vector<uhd::rfnoc::graph_edge_t>::iterator iter = active_connections.begin(); // Print active connections for(iter; iter < active_connections.end(); iter++) { std::cout << (*iter).to_string() << std::endl;; } rx_radio_ctrl->enable_rx_timestamps(rx_timestamps, rx_chan); // Set time and clock reference for (size_t i = 0; i < graph->get_num_mboards(); ++i) { graph->get_mb_controller(i)->set_clock_source(ref); } // Lock mboard clocks for (size_t i = 0; i < graph->get_num_mboards(); ++i) { graph->get_mb_controller(i)->set_time_source(pps); } rate = rx_radio_ctrl->set_rate(rate); // set the sample rate std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate / 1e6) << std::endl; rate = rx_radio_ctrl->set_rate(rate); std::cout << boost::format("Actual RX Rate: %f Msps...") % (rate / 1e6) << std::endl << std::endl; // set the center frequency std::cout << boost::format("Setting RX Freq: %f MHz...") % (rx_freq / 1e6) << std::endl; rx_radio_ctrl->set_rx_frequency(rx_freq, rx_chan); std::cout << boost::format("Actual RX Freq: %f MHz...") % (rx_radio_ctrl->get_rx_frequency(rx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Freq: %f MHz...") % (tx_freq / 1e6) << std::endl; tx_radio_ctrl->set_tx_frequency(tx_freq, tx_chan); std::cout << boost::format("Actual TX Freq: %f MHz...") % (tx_radio_ctrl->get_tx_frequency(tx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % (rx_bw / 1e6) << std::endl; rx_radio_ctrl->set_rx_bandwidth(rx_bw, rx_chan); std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % (rx_radio_ctrl->get_rx_bandwidth(rx_chan) / 1e6) << std::endl << std::endl; std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % (tx_bw / 1e6) << std::endl; tx_radio_ctrl->set_tx_bandwidth(tx_bw, tx_chan); std::cout << boost::format("Actual TX Bandwidth: %f MHz...") % (tx_radio_ctrl->get_tx_bandwidth(tx_chan) / 1e6) << std::endl << std::endl; // Antennas rx_radio_ctrl->set_rx_antenna("A", 0); rx_radio_ctrl->set_rx_antenna("B", 1); tx_radio_ctrl->set_tx_antenna("A", 0); rx_radio_ctrl->set_tx_antenna("A", 0); std::cout << "Setting samples per packet to: " << spp << std::endl; rx_radio_ctrl->set_property<int>("spp", spp, 0); spp = rx_radio_ctrl->get_property<int>("spp", 0); std::cout << "Actual samples per packet = " << spp << std::endl; // Allow for some setup time std::this_thread::sleep_for(1s * setup_time); // Arm SIGINT handler std::signal(SIGINT, &sig_int_handler); // Calculate timeout and set timers // We just need to check is nsamps was set, otherwise we'll use the duration if (total_num_samps > 0) { total_time = total_num_samps / rate; std::cout << boost::format("Expected streaming time: %.3f") % total_time << std::endl; } // Start streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); stream_cmd.num_samps = size_t(total_num_samps); stream_cmd.stream_now = false; stream_cmd.time_spec = graph->get_mb_controller(rx_mb_idx)->get_timekeeper(rx_mb_idx)->get_time_now() + setup_time; std::cout << "Issuing start stream cmd..." << std::endl; // Are two stream commands required for 2 channel RX? rx_radio_ctrl->issue_stream_cmd(stream_cmd, 0); rx_radio_ctrl->issue_stream_cmd(stream_cmd, 1); std::this_thread::sleep_for(1s * setup_time); std::cout << "Wait..." << std::endl; // Wait until we can exit uhd::time_spec_t elapsed_time = 0.0; while (not stop_signal_called) { std::this_thread::sleep_for(100ms); if (total_time > 0.0) { elapsed_time += 0.1; if (elapsed_time > total_time) { break; } } } // Stop radio stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS; std::cout << "Issuing stop stream cmd..." << std::endl; rx_radio_ctrl->issue_stream_cmd(stream_cmd, rx_chan); std::cout << "Done" << std::endl; // Allow for the samples and ACKs to propagate std::this_thread::sleep_for(100ms); return EXIT_SUCCESS; }
_______________________________________________ USRP-users mailing list -- usrp-users@lists.ettus.com To unsubscribe send an email to usrp-users-le...@lists.ettus.com