mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
example: cpp: Enhanced documentation for rfnoc_* examples
- Added program documentation string. - Marked required options as required(). - Added short option strings for required options. - Made individual option descriptions more descriptive. - Harmonized naming of options where appropriate. Introduced alias options for renamed options to keep backward compatibility.
This commit is contained in:
parent
981d2d41e1
commit
fbc5ad9eb0
@ -202,42 +202,80 @@ void pretty_print_flow_graph(std::vector<std::string> blocks)
|
||||
///////////////////// MAIN ////////////////////////////////////////////////////
|
||||
int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
{
|
||||
const std::string program_doc =
|
||||
"usage: rfnoc_nullsource_ce_rx [-h] [--args ARGS] [--file FILE] [--null]\n"
|
||||
" [--time TIME] [--spb SPB] [--spp SPP]\n"
|
||||
" [--throttle-cycles THROTTLE_CYCLES]\n"
|
||||
" [--format {double,float,short}]\n"
|
||||
" [--progress] [--stats] [--continue]\n"
|
||||
" [--nullid NULLID]"
|
||||
"\n\n"
|
||||
"This example demonstrates how to use the RFNoC Null Source/Sink block to\n"
|
||||
"generate and stream test data. The program requires an FPGA image that\n"
|
||||
"includes the RFNoC Null Source/Sink block. It is useful for verifying\n"
|
||||
"RFNoC data paths and testing system connectivity without external\n"
|
||||
"signals. Generated data is also written to a file for validation\n"
|
||||
"purposes.\n"
|
||||
"\n"
|
||||
"Usage example:\n"
|
||||
" Receive 1 second of samples from the RFNoC Null Source/Sink block\n"
|
||||
" and display statistics:\n"
|
||||
" rfnoc_nullsource_ce_rx --args \"addr=192.168.10.2\"\n"
|
||||
" --nullid \"0/NullSrcSink#0\"\n"
|
||||
" --spb 10000 --spp 256 --throttle-cycles 0\n"
|
||||
" --progress --stats --time 1\n";
|
||||
|
||||
// variables to be set by po
|
||||
std::string args, file, format, nullid;
|
||||
size_t spb, spp, throttle_cycles;
|
||||
double rate, total_time;
|
||||
double total_time;
|
||||
|
||||
// setup the program options
|
||||
po::options_description desc("Allowed options");
|
||||
// clang-format off
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("args", po::value<std::string>(&args)->default_value("type=x300"), "multi uhd device address args")
|
||||
("file", po::value<std::string>(&file)->default_value("graph_samples.dat"), "name of the file to write binary samples to, set to stdout to print")
|
||||
("null", "run without writing to file")
|
||||
("time", po::value<double>(&total_time)->default_value(0), "total number of seconds to receive")
|
||||
("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer")
|
||||
("spp", po::value<size_t>(&spp)->default_value(64), "samples per packet (on FPGA and wire)")
|
||||
("throttle-cycles", po::value<size_t>(&throttle_cycles)->default_value(0), "Number of cycles to force in between packets")
|
||||
("rate", po::value<double>(&rate)->default_value(1e6), "rate at which samples are produced in the null source")
|
||||
("format", po::value<std::string>(&format)->default_value("sc16"), "File sample type: sc16, fc32, or fc64")
|
||||
("progress", "periodically display short-term bandwidth")
|
||||
("stats", "show average bandwidth on exit")
|
||||
("continue", "don't abort on a bad packet")
|
||||
("nullid", po::value<std::string>(&nullid)->default_value("0/NullSrcSink#0"), "The block ID for the null source.")
|
||||
("help,h", "Show this help message and exit.")
|
||||
("args", po::value<std::string>(&args)->default_value("type=x300"), "Single USRP device selection and "
|
||||
"configuration arguments."
|
||||
"\nSpecify key-value pairs (e.g., addr, serial, type, master_clock_rate) separated by commas."
|
||||
"\nSee the UHD manual for model-specific options."
|
||||
"\nExamples:"
|
||||
"\n --args \"addr=192.168.10.2\""
|
||||
"\n --args \"addr=192.168.10.2,master_clock_rate=200e6\""
|
||||
"\nIf not specified, UHD connects to the first available device.")
|
||||
("file", po::value<std::string>(&file)->default_value("graph_samples.dat"), "Name of the raw binary "
|
||||
"file to which received data will be written.")
|
||||
("null", "Run without writing to file.")
|
||||
("time", po::value<double>(&total_time)->default_value(0), "Total number of seconds to receive.")
|
||||
("spb", po::value<size_t>(&spb)->default_value(10000), "Size of the host data buffer in samples.")
|
||||
("spp", po::value<size_t>(&spp)->default_value(64), "Specifies the number of samples per packet sent "
|
||||
"from the FPGA to the host. Adjusting this value can affect streaming efficiency and packetization behavior.")
|
||||
("throttle-cycles", po::value<size_t>(&throttle_cycles)->default_value(0), "Number of cycles to force "
|
||||
"in between packets.")
|
||||
("format", po::value<std::string>(&format)->default_value("sc16"), "Specifies the data format of the "
|
||||
"file. The data will be written as interleaved IQ samples in one of the following numeric formats: 'double' "
|
||||
"(64-bit float, fc64), 'float' (32-bit float, fc32), or 'short' (16-bit integer, sc16, scaled to int16 range "
|
||||
"-32768 to 32767)."
|
||||
"\nChoosing 'short' as the file format matches the sc16 over-the-wire format and is usually sufficient. Using "
|
||||
"'float' or 'double' does not improve precision, but may be more convenient for post-processing or for "
|
||||
"compatibility with certain analysis tools.")
|
||||
("progress", "Periodically display the estimated short-term USRP device to host streaming rate in "
|
||||
"samples per second.")
|
||||
("stats", "Show the total number of samples received and the elapsed time when the program exits.")
|
||||
("continue", "Continue streaming even if a bad packet is received.")
|
||||
("nullid", po::value<std::string>(&nullid)->default_value("0/NullSrcSink#0"), "The block ID for the "
|
||||
"null source. Format is typically \"mboard_index/NullSrcSink#N\" (e.g. \"0/NullSrcSink#0\").")
|
||||
;
|
||||
// clang-format on
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
// print the help message
|
||||
if (vm.count("help")) {
|
||||
std::cout << "[RFNOC] Connect a null source to another (processing) block, "
|
||||
"and stream the result to file."
|
||||
<< desc << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
std::cout << program_doc << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return ~0;
|
||||
}
|
||||
po::notify(vm); // only called if --help was not requested
|
||||
|
||||
bool bw_summary = vm.count("progress") > 0;
|
||||
bool stats = vm.count("stats") > 0;
|
||||
@ -285,7 +323,7 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
stream_args_args["block_id"] = nullid;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//////// 4. Configure blocks (packet size and rate) /////////////////////
|
||||
//////// 4. Configure blocks (packet size) //////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
std::cout << "Samples per packet coming from null source: " << spp << std::endl;
|
||||
const size_t BYTES_PER_SAMPLE = 4;
|
||||
|
||||
@ -41,6 +41,42 @@ void sig_int_handler(int)
|
||||
***************************************************************************/
|
||||
int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
{
|
||||
const std::string program_doc =
|
||||
"usage: rfnoc_radio_loopback [-h] [--args ARGS] [--spp SPP]\n"
|
||||
" [--rx-freq RX_FREQ] [--tx-freq TX_FREQ]\n"
|
||||
" [--rx-gain RX_GAIN] [--tx-gain TX_GAIN]\n"
|
||||
" [--rx-ant RX_ANT] [--tx-ant TX_ANT]\n"
|
||||
" [--rx-blockid RX_BLOCKID]\n"
|
||||
" [--tx-blockid TX_BLOCKID]\n"
|
||||
" [--rx-chan RX_CHAN] [--tx-chan TX_CHAN]\n"
|
||||
" [--rx-bw RX_BW] [--tx-bw TX_BW]\n"
|
||||
" [--rx-timestamps RX_TIMESTAMPS]\n"
|
||||
" [--setup SETUP] [--nsamps NSAMPS]\n"
|
||||
" [-r RATE] [--duration DURATION] [--int-n]\n"
|
||||
" [--ref {internal,external,mimo,gpsdo}]\n"
|
||||
" [--pps {internal,external,mimo,gpsdo}]\n"
|
||||
" [--dot]"
|
||||
"\n\n"
|
||||
"This example streams baseband data from a selected RFNoC RX radio block\n"
|
||||
"and channel to a TX radio block and channel.\n"
|
||||
"The connection is dynamically established between the RX radio and TX\n"
|
||||
"radio; if DDC and DUC blocks are present, data is routed through them\n"
|
||||
"for digital down/up conversion. Streaming can be performed for a\n"
|
||||
"user-defined duration or continuously.\n"
|
||||
"\n"
|
||||
"Key features:\n"
|
||||
"- Dynamically connects RX radio (or DDC) to TX radio (or DUC) using\n"
|
||||
" RFNoC.\n"
|
||||
"- Flexible selection of radio blocks and channels.\n"
|
||||
"- Configurable sample rate, frequency, gain, bandwidth, and antenna for\n"
|
||||
" both RX and TX.\n"
|
||||
"- Shows how to enable timestamping of RX packets.\n"
|
||||
"\n"
|
||||
"Usage example:\n"
|
||||
"Receive a signal at 3.5 GHz at re-transmit it at 2.4 GHz using the\n"
|
||||
"default radio sampling rate and using two different RFNoC radio blocks:\n"
|
||||
" rfnoc_radio_loopback --args \"addr=192.168.10.2\"\n"
|
||||
" --rx-blockid \"0/Radio#0\" --tx-blockid \"0/Radio#1\"";
|
||||
// variables to be set by po
|
||||
std::string args, rx_ant, tx_ant, rx_blockid, tx_blockid, ref, pps;
|
||||
size_t total_num_samps, spp, rx_chan, tx_chan;
|
||||
@ -51,44 +87,73 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
po::options_description desc("Allowed options");
|
||||
// clang-format off
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "UHD device address args")
|
||||
("spp", po::value<size_t>(&spp)->default_value(0), "Samples per packet (reduce for lower latency)")
|
||||
("rx-freq", po::value<double>(&rx_freq)->default_value(0.0), "Rx RF center frequency in Hz")
|
||||
("tx-freq", po::value<double>(&tx_freq)->default_value(0.0), "Tx RF center frequency in Hz")
|
||||
("rx-gain", po::value<double>(&rx_gain)->default_value(0.0), "Rx RF center gain in Hz")
|
||||
("tx-gain", po::value<double>(&tx_gain)->default_value(0.0), "Tx RF center gain in Hz")
|
||||
("rx-ant", po::value<std::string>(&rx_ant), "Receive antenna selection")
|
||||
("tx-ant", po::value<std::string>(&tx_ant), "Transmit antenna selection")
|
||||
("rx-blockid", po::value<std::string>(&rx_blockid)->default_value("0/Radio#0"), "Receive radio block ID")
|
||||
("tx-blockid", po::value<std::string>(&tx_blockid)->default_value("0/Radio#1"), "Transmit radio block ID")
|
||||
("rx-chan", po::value<size_t>(&rx_chan)->default_value(0), "Channel index on receive radio")
|
||||
("tx-chan", po::value<size_t>(&tx_chan)->default_value(0), "Channel index on transmit radio")
|
||||
("rx-bw", po::value<double>(&rx_bw), "RX analog frontend filter bandwidth in Hz")
|
||||
("tx-bw", po::value<double>(&tx_bw), "TX analog frontend filter bandwidth in Hz")
|
||||
("rx-timestamps", po::value<bool>(&rx_timestamps)->default_value(false), "Set timestamps on RX")
|
||||
("setup", po::value<double>(&setup_time)->default_value(0.1), "seconds of setup time")
|
||||
("nsamps", po::value<size_t>(&total_num_samps)->default_value(0), "total number of samples to receive")
|
||||
("rate", po::value<double>(&rate)->default_value(0.0), "Sampling rate")
|
||||
("duration", po::value<double>(&total_time)->default_value(0), "total number of seconds to receive")
|
||||
("int-n", "Tune USRP with integer-N tuning")
|
||||
("ref", po::value<std::string>(&ref), "clock reference (internal, external, gpsdo, mimo)")
|
||||
("pps", po::value<std::string>(&pps), "PPS source (internal, external, mimo, gpsdo)")
|
||||
("help,h", "Show this help message and exit.")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "Single USRP device selection and "
|
||||
"configuration arguments."
|
||||
"\nSpecify key-value pairs (e.g., addr, serial, type, master_clock_rate) separated by commas."
|
||||
"\nSee the UHD manual for model-specific options."
|
||||
"\nExamples:"
|
||||
"\n --args \"addr=192.168.10.2\""
|
||||
"\n --args \"addr=192.168.10.2,master_clock_rate=200e6\""
|
||||
"\nIf not specified, UHD connects to the first available device.")
|
||||
("spp", po::value<size_t>(&spp)->default_value(0), "Specifies the number of samples per packet sent "
|
||||
"from the RFNoC radio block. Use smaller values to reduce latency.")
|
||||
("rx-freq", po::value<double>(&rx_freq)->default_value(0.0), "RX RF center frequency in Hz.")
|
||||
("tx-freq", po::value<double>(&tx_freq)->default_value(0.0), "TX RF center frequency in Hz.")
|
||||
("rx-gain", po::value<double>(&rx_gain)->default_value(0.0), "RX gain for the RF chain in dB.")
|
||||
("tx-gain", po::value<double>(&tx_gain)->default_value(0.0), "TX gain for the RF chain in dB.")
|
||||
("rx-ant", po::value<std::string>(&rx_ant), "RX antenna port selection string selecting a specific "
|
||||
"antenna port for USRP daughterboards having multiple antenna connectors per RF channel."
|
||||
"\nExample: --ant \"TX/RX\"")
|
||||
("tx-ant", po::value<std::string>(&tx_ant), "TX antenna port selection string selecting a specific "
|
||||
"antenna port for USRP daughterboards having multiple antenna connectors per RF channel."
|
||||
"\nExample: --ant \"TX/RX\"")
|
||||
("rx-blockid", po::value<std::string>(&rx_blockid)->default_value("0/Radio#0"), "Specifies the RFNoC "
|
||||
"radio block ID to use for receiving. Format is typically \"mboard_index/Radio#N\" (e.g., 0/Radio#0).")
|
||||
("tx-blockid", po::value<std::string>(&tx_blockid)->default_value("0/Radio#1"), "Specifies the RFNoC "
|
||||
"radio block ID to use for transmitting. Format is typically \"mboard_index/Radio#N\" (e.g., 0/Radio#1).")
|
||||
("rx-chan", po::value<size_t>(&rx_chan)->default_value(0), "Selects the channel index within the "
|
||||
"chosen RX radio block for data reception (e.g., 0 for the first channel).")
|
||||
("tx-chan", po::value<size_t>(&tx_chan)->default_value(0), "Selects the channel index within the "
|
||||
"chosen TX radio block for data transmission (e.g., 0 for the first channel).")
|
||||
("rx-bw", po::value<double>(&rx_bw), "Sets the analog frontend filter bandwidth for the RX path in "
|
||||
"Hz. Not all USRP devices support programmable bandwidth; if an unsupported value is requested, the device "
|
||||
"will use the nearest supported bandwidth instead.")
|
||||
("tx-bw", po::value<double>(&tx_bw), "Sets the analog frontend filter bandwidth for the TX path in "
|
||||
"Hz. Not all USRP devices support programmable bandwidth; if an unsupported value is requested, the device "
|
||||
"will use the nearest supported bandwidth instead.")
|
||||
("rx-timestamps", po::value<bool>(&rx_timestamps)->default_value(false), "Enables timestamping on "
|
||||
"received packets, associating each sample with a precise time value.")
|
||||
("setup", po::value<double>(&setup_time)->default_value(0.1), "Sets the amount of time (in seconds) "
|
||||
"the program waits for hardware locks (e.g. LO) to ensure the device is properly synchronized before starting "
|
||||
"reception.")
|
||||
("nsamps", po::value<size_t>(&total_num_samps)->default_value(0), "Total number of samples to "
|
||||
"receive. The program stops when this number is reached.")
|
||||
("rate,r", po::value<double>(&rate)->default_value(0.0), "Sets the sample rate for both RX and TX "
|
||||
"radio blocks. The specified rate must be supported by the selected radio; supported values differ between "
|
||||
"USRP models. Refer to the UHD manual for valid sample rates for your hardware.")
|
||||
("duration", po::value<double>(&total_time)->default_value(0), "Total number of seconds to receive. "
|
||||
"The program stops when this number is reached.")
|
||||
("int-n", "Use integer-N tuning for USRP RF synthesizers. With this mode, the LO can only be tuned in "
|
||||
"discrete steps, which are integer multiples of the reference frequency. This mode can improve phase noise "
|
||||
"and spurious performance at the cost of coarser frequency resolution.")
|
||||
("ref", po::value<std::string>(&ref), "Sets the source for the frequency reference. Available values "
|
||||
"depend on the USRP model. Typical values are 'internal', 'external', 'mimo', and 'gpsdo'.")
|
||||
("pps", po::value<std::string>(&pps), "Specifies the PPS source for time synchronization. Available "
|
||||
"values depend on the USRP model. Typical values are 'internal', 'external', 'mimo', and 'gpsdo'.")
|
||||
("dot", "Outputs the RFNoC graph as a DOT-format representation, showing the connections between "
|
||||
"blocks for visualization or analysis.")
|
||||
;
|
||||
// clang-format on
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
// print the help message
|
||||
if (vm.count("help")) {
|
||||
std::cout << boost::format("RFNoC: Radio loopback test %s") % desc << std::endl;
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< "This application streams data from one radio to another using RFNoC.\n"
|
||||
<< std::endl;
|
||||
std::cout << program_doc << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return ~0;
|
||||
}
|
||||
po::notify(vm); // only called if --help was not requested
|
||||
|
||||
/************************************************************************
|
||||
* Create device and block controls
|
||||
@ -123,6 +188,14 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
uhd::rfnoc::connect_through_blocks(
|
||||
graph, rx_radio_ctrl_id, rx_chan, tx_radio_ctrl_id, tx_chan, skip_pp);
|
||||
graph->commit();
|
||||
std::cout << "Active connections:" << std::endl;
|
||||
if (vm.count("dot")) {
|
||||
std::cout << graph->to_dot() << std::endl;
|
||||
} else {
|
||||
for (auto& edge : graph->enumerate_active_connections()) {
|
||||
std::cout << "* " << edge.to_string() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
rx_radio_ctrl->enable_rx_timestamps(rx_timestamps, rx_chan);
|
||||
|
||||
@ -154,6 +227,8 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
<< std::endl
|
||||
<< std::endl;
|
||||
}
|
||||
std::cout << "Actual Sample Rate: " << (rate / 1e6) << " Msps..." << std::endl
|
||||
<< std::endl;
|
||||
|
||||
// set the center frequency
|
||||
if (vm.count("rx-freq")) {
|
||||
|
||||
@ -46,6 +46,72 @@ void sig_int_handler(int)
|
||||
|
||||
int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
{
|
||||
// clang-format off
|
||||
const std::string program_doc =
|
||||
"usage: rfnoc_replay_samples_from_file [-h] [--args ARGS] -f FREQ [-r RATE]\n"
|
||||
" [--tx-args TX_ARGS]\n"
|
||||
" [--radio-id RADIO_ID]\n"
|
||||
" [--radio-chan RADIO_CHAN]\n"
|
||||
" [--replay-id REPLAY_ID]\n"
|
||||
" [--replay-chan REPLAY_CHAN]\n"
|
||||
" [--nsamps NSAMPS] [--file FILE]\n"
|
||||
" [--lo-offset LO_OFFSET]\n"
|
||||
" [--gain GAIN] [--ant ANT]\n"
|
||||
" [--bw BW]\n"
|
||||
" [--ref {internal,external,mimo,gpsdo}]\n"
|
||||
" [--dot]"
|
||||
"\n\n"
|
||||
"This example program demonstrates how to use the RFNoC C++ API\n"
|
||||
"to create an RFNoC graph involving an RFNoC Replay block for playback of\n"
|
||||
"baseband samples through the radio.\n"
|
||||
"The program loads sample data into the Replay block, configures the RF\n"
|
||||
"chain, and plays back the data through the radio. Playback can be\n"
|
||||
"continuous or for a specified number of samples.\n"
|
||||
"\n"
|
||||
"Notes:\n"
|
||||
" - The Replay block is included in most default FPGA images for\n"
|
||||
" RFNoC-capable USRP devices, so custom FPGA builds are usually not\n"
|
||||
" required to use this example program.\n"
|
||||
" - The USRP may round the requested transmit sample rate to the nearest\n"
|
||||
" supported value. For accurate playback, please ensure that the sample\n"
|
||||
" rate of the input data in the file matches the USRP sample rate.\n"
|
||||
" If supported by your USRP device model, you could also change the\n"
|
||||
" master clock rate to an integer multiple of the desired sample rate\n"
|
||||
" to achieve precise sampling. For available master clock rates for a\n"
|
||||
" specific USRP device model, see the UHD manual.\n"
|
||||
"\n"
|
||||
"Key features:\n"
|
||||
"- Loads baseband samples from a binary file and uploads them to the\n"
|
||||
" RFNoC Replay block for playback through the radio.\n"
|
||||
"- Dynamically builds and configures an RFNoC graph connecting the Replay\n"
|
||||
" block to the radio block, with automatic integration of a DUC block if\n"
|
||||
" present.\n"
|
||||
"- Supports flexible selection of Replay and radio blocks and channels\n"
|
||||
" via program options.\n"
|
||||
"- Allows configuration of key transmission parameters, including\n"
|
||||
" frequency, sample rate, gain, bandwidth, LO offset, and antenna.\n"
|
||||
"- Enables continuous or finite playback of samples, as specified by the\n"
|
||||
" user.\n"
|
||||
"\n"
|
||||
"Usage examples:\n"
|
||||
"1. Replay a signal from a file on default radio and using default replay\n"
|
||||
" block.\n"
|
||||
" rfnoc_replay_samples_from_file --args \"addr=192.168.10.2\"\n"
|
||||
" --freq 2.4e09 --rate 10e06\n"
|
||||
" --file usrp_samples.dat\n"
|
||||
"2. Replay a signal from a file explicitly selecting and configuring the\n"
|
||||
" radio and replay block:\n"
|
||||
" rfnoc_replay_samples_from_file --args \"addr=192.168.10.2\"\n"
|
||||
" --freq 2.4e09 --rate 10e06\n"
|
||||
" --file usrp_samples.dat\n"
|
||||
" --radio-id 1 --radio-chan 0\n"
|
||||
" --replay-id 0 --replay-chan 0\n"
|
||||
"3. Replay an LTE signal at a sampling rate of 30.72MSps with master\n"
|
||||
" clock rate changed to an integer multiple of the sampling rate:\n"
|
||||
" rfnoc_replay_samples_from_file --args \"addr=192.168.10.2,master_clock_rate=184.32e6\"\n"
|
||||
" --freq 2.4e09 --rate 30.72e06\n"
|
||||
" --file LTE_30d72MSps_sc16.dat\n";
|
||||
// clang-format on
|
||||
// We use sc16 in this example, but the replay block only uses 64-bit words
|
||||
// and is not aware of the CPU or wire format.
|
||||
std::string wire_format("sc16");
|
||||
@ -59,41 +125,75 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
size_t radio_id, radio_chan, replay_id, replay_chan, nsamps;
|
||||
|
||||
po::options_description desc("Allowed Options");
|
||||
po::options_description alias_options;
|
||||
po::options_description all_options;
|
||||
// clang-format off
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args")
|
||||
("tx_args", po::value<std::string>(&tx_args), "Block args for the transmit radio")
|
||||
("radio_id", po::value<size_t>(&radio_id)->default_value(0), "radio block to use (e.g., 0 or 1).")
|
||||
("radio_chan", po::value<size_t>(&radio_chan)->default_value(0), "radio channel to use")
|
||||
("replay_id", po::value<size_t>(&replay_id)->default_value(0), "replay block to use (e.g., 0 or 1)")
|
||||
("replay_chan", po::value<size_t>(&replay_chan)->default_value(0), "replay channel to use")
|
||||
("nsamps", po::value<size_t>(&nsamps)->default_value(0), "number of samples to play (0 for infinite)")
|
||||
("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the file to read binary samples from")
|
||||
("freq", po::value<double>(&freq), "RF center frequency in Hz")
|
||||
("lo-offset", po::value<double>(&lo_offset), "Offset for frontend LO in Hz (optional)")
|
||||
("rate", po::value<double>(&rate), "rate of radio block")
|
||||
("gain", po::value<double>(&gain), "gain for the RF chain")
|
||||
("ant", po::value<std::string>(&ant), "antenna selection")
|
||||
("bw", po::value<double>(&bw), "analog front-end filter bandwidth in Hz")
|
||||
("ref", po::value<std::string>(&ref), "clock reference (internal, external, mimo, gpsdo)")
|
||||
("dot", "instead of a textual representation, generate a dot graph of the RFNoC connections")
|
||||
("help,h", "Show this help message and exit.")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "Single USRP device selection and "
|
||||
"configuration arguments."
|
||||
"\nSpecify key-value pairs (e.g., addr, serial, type, master_clock_rate) separated by commas."
|
||||
"\nSee the UHD manual for model-specific options."
|
||||
"\nExamples:"
|
||||
"\n --args \"addr=192.168.10.2\""
|
||||
"\n --args \"addr=192.168.10.2,master_clock_rate=200e6\""
|
||||
"\nIf not specified, UHD connects to the first available device.")
|
||||
("tx-args", po::value<std::string>(&tx_args), "Provides additional configuration options for the TX "
|
||||
"radio block as key-value pairs (e.g., mode_n, lo_source). The available options depend on the USRP model. "
|
||||
"Refer to the UHD manual for a complete list and details of supported arguments for your hardware.")
|
||||
("radio-id", po::value<size_t>(&radio_id)->default_value(0), "Specifies the RFNoC radio block index "
|
||||
"to use for transmission. On devices with multiple radio blocks, this argument selects which RF frontend "
|
||||
"(e.g., 0 for the first radio, 1 for the second) is addressed for streaming.")
|
||||
("radio-chan", po::value<size_t>(&radio_chan)->default_value(0), "Selects the channel index within "
|
||||
"the chosen RFNoC radio block for data transmission. This determines which physical transmit channel (e.g., 0 "
|
||||
"for the first channel, 1 for the second) is used for streaming.")
|
||||
("replay-id", po::value<size_t>(&replay_id)->default_value(0), "Specifies the RFNoC Replay block "
|
||||
"index to use for playback (e.g., 0 for the first Replay block).")
|
||||
("replay-chan", po::value<size_t>(&replay_chan)->default_value(0), "Selects the channel index within "
|
||||
"the chosen Replay block for data playback.")
|
||||
("nsamps", po::value<size_t>(&nsamps)->default_value(0), "Sets the total number of samples to play "
|
||||
"back from the file. If set to 0, playback is continuous; otherwise, playback stops after the specified "
|
||||
"number of samples.")
|
||||
("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "Specifies the name of the "
|
||||
"binary file containing baseband samples to be loaded into the Replay block for playback."
|
||||
"\nThis example program requires the input file to use the sc16 format (interleaved 16-bit signed integers for "
|
||||
"I/Q), although the Replay block itself can support other data formats.")
|
||||
("freq,f", po::value<double>(&freq)->required(), "RF center frequency in Hz.")
|
||||
("lo-offset", po::value<double>(&lo_offset), "LO offset for the frontend in Hz.")
|
||||
("rate,r", po::value<double>(&rate), "TX sample rate in samples/second. Note that each "
|
||||
"USRP device only supports a set of discrete sample rates, which depend on the hardware model and "
|
||||
"configuration. If you request a rate that is not supported, the USRP device will automatically select and "
|
||||
"use the closest available rate.")
|
||||
("gain", po::value<double>(&gain), "TX gain for the RF chain in dB.")
|
||||
("ant", po::value<std::string>(&ant), "Antenna port selection string selecting a specific antenna "
|
||||
"port for USRP daughterboards having multiple antenna connectors per RF channel."
|
||||
"\nExample: --ant \"TX/RX\"")
|
||||
("bw", po::value<double>(&bw), "Sets the analog frontend filter bandwidth for the TX path in Hz. Not "
|
||||
"all USRP devices support programmable bandwidth; if an unsupported value is requested, the device will use "
|
||||
"the nearest supported bandwidth instead.")
|
||||
("ref", po::value<std::string>(&ref), "Sets the source for the frequency reference. Available values "
|
||||
"depend on the USRP model. Typical values are 'internal', 'external', 'mimo', and 'gpsdo'.")
|
||||
("dot", "Outputs the RFNoC graph as a DOT-format representation, showing the connections between "
|
||||
"blocks for visualization or analysis.")
|
||||
;
|
||||
alias_options.add_options()
|
||||
("tx_args", po::value<std::string>(&tx_args), "") // alias for --tx-args for backward compatibility
|
||||
("radio_id", po::value<size_t>(&radio_id), "") // alias for --radio-id
|
||||
("radio_chan", po::value<size_t>(&radio_chan), "") // alias for --radio-chan
|
||||
("replay_id", po::value<size_t>(&replay_id), "") // alias for --replay-id
|
||||
("replay_chan", po::value<size_t>(&replay_chan), "") // alias for --replay-chan
|
||||
;
|
||||
all_options.add(desc).add(alias_options);
|
||||
// clang-format on
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
// Print help message
|
||||
po::store(po::parse_command_line(argc, argv, all_options), vm);
|
||||
// print the help message
|
||||
if (vm.count("help")) {
|
||||
cout << "UHD/RFNoC Replay samples from file " << desc << endl;
|
||||
cout << "This application uses the Replay block to playback data from a file to "
|
||||
"a radio"
|
||||
<< endl
|
||||
<< endl;
|
||||
return EXIT_FAILURE;
|
||||
std::cout << program_doc << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return ~0;
|
||||
}
|
||||
|
||||
po::notify(vm); // only called if --help was not requested
|
||||
|
||||
/************************************************************************
|
||||
* Create device and block controls
|
||||
|
||||
@ -222,6 +222,83 @@ bool check_locked_sensor(std::vector<std::string> sensor_names,
|
||||
|
||||
int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
{
|
||||
const std::string program_doc =
|
||||
"usage: rfnoc_rx_to_file [--help] [--args ARGS] [--file FILE]\n"
|
||||
" [--format FORMAT] [--duration DURATION]\n"
|
||||
" [--nsamps NSAMPS] [--spb SPB] [--spp SPP]\n"
|
||||
" [--streamargs STREAMARGS] [--progress]\n"
|
||||
" [--stats] [--sizemap] [--null] [--continue]\n"
|
||||
" [--setup SETUP] [--radio-id RADIO_ID]\n"
|
||||
" [--radio-chan RADIO_CHAN] [--rate RATE]\n"
|
||||
" [--freq FREQ] [--lo-offset LO_OFFSET]\n"
|
||||
" [--gain GAIN] [--ant ANT] [--bw BW]\n"
|
||||
" [--ref {internal,external,mimo,gpsdo}]\n"
|
||||
" [--skip-lo] [--int-n] [--block-id BLOCK_ID]\n"
|
||||
" [--block-port BLOCK_PORT]\n"
|
||||
" [--block-props BLOCK_PROPS]"
|
||||
"\n\n"
|
||||
"This example demonstrates how to use the RFNoC C++ API to\n"
|
||||
"receive samples from a single channel of a single USRP device.\n"
|
||||
"It builds and configures an RFNoC graph that connects the radio block\n"
|
||||
"(RF frontend) to the DDC (digital downconverter, if present), and then\n"
|
||||
"to the host RxStreamer.\n"
|
||||
"If specified, an additional RFNoC processing block can be inserted into\n"
|
||||
"the chain; the graph is built dynamically so that received samples are\n"
|
||||
"processed by this block, enabling customized RX sample processing.\n"
|
||||
"The received data is streamed to a raw binary file on the host.\n"
|
||||
"\n"
|
||||
"Note: The additional RFNoC block must be available in the FPGA, which\n"
|
||||
"typically requires a custom FPGA build synthesizing extra RFNoC blocks\n"
|
||||
"such as FFT or FIR into the design.\n"
|
||||
"\n"
|
||||
"Key features:\n"
|
||||
"- Builds an RFNoC graph that connects the RxStreamer, Radio, and DDC (if\n"
|
||||
" present) RFNoC blocks for sample acquisition.\n"
|
||||
"- Supports flexible insertion of an optional RFNoC processing block into\n"
|
||||
" the signal chain, as specified by the --block-id option, allowing\n"
|
||||
" users to process samples with custom FPGA logic prior to file capture.\n"
|
||||
"- Configures all involved RFNoC blocks, including the RxStreamer, Radio,\n"
|
||||
" and DDC. If an additional RFNoC processing block is inserted via the\n"
|
||||
" --block-id option, it is configured with the block properties\n"
|
||||
" specified by the --block-props option.\n"
|
||||
"- Automatically sets up connections between RFNoC blocks and configures\n"
|
||||
" streaming parameters according to user-specified options, ensuring\n"
|
||||
" that all selected blocks are properly integrated into the signal\n"
|
||||
" chain.\n"
|
||||
"\n"
|
||||
"Usage examples:\n"
|
||||
" 1. Receive 10 ms data at 2.4 GHz using a sample rate of 10 MSps and\n"
|
||||
" save it to file:\n"
|
||||
" rfnoc_rx_to_file --args \"addr=192.168.10.2\" --freq 2.4e09\n"
|
||||
" --rate 10e06 --duration 0.01\n"
|
||||
" --file \"usrp_samples.dat\"\n"
|
||||
" The program will print the RFNoC connections, that were created\n"
|
||||
" to propagate the data from the radio to the RX streamer. E.g.\n"
|
||||
" this might look like:\n"
|
||||
" Active connections:\n"
|
||||
" * 0/Radio#0:0==>0/DDC#0:0\n"
|
||||
" * 0/DDC#0:0-->RxStreamer#0:0\n"
|
||||
" 2. Use Radio 1 to receive 10 ms data at 2.4 GHz using a sample rate of\n"
|
||||
" 10 MSps and save it to file:\n"
|
||||
" rfnoc_rx_to_file --args \"addr=192.168.10.2\" --radio-id 1\n"
|
||||
" --radio-chan 0 --freq 2.4e09 --rate 10e06\n"
|
||||
" --duration 0.01 --file usrp_samples.dat\"\n"
|
||||
" The printed RFNoC connections now show that Radio 1 is used:\n"
|
||||
" Active connections:\n"
|
||||
" * 0/Radio#1:0==>0/DDC#1:0\n"
|
||||
" * 0/DDC#1:0-->RxStreamer#0:0\n"
|
||||
" 3. Insert an RFNoC FFT block into the RFNoC block chain:\n"
|
||||
" rfnoc_rx_to_file --args \"addr=192.168.10.2\"\n"
|
||||
" --block-id \"0/FFT#0\" --block-port 0\n"
|
||||
" --block-props \"bypass_mode=1\"\n"
|
||||
" --freq 2.4e09 --rate 10e06 --duration 0.01\n"
|
||||
" The printed RFNoC connections now show that the FFT block got\n"
|
||||
" inserted in between the DDC and the RxStreamer:\n"
|
||||
" Active connections:\n"
|
||||
" * 0/Radio#0:0==>0/DDC#0:0\n"
|
||||
" * 0/DDC#0:0-->0/FFT#0:0\n"
|
||||
" * 0/FFT#0:0-->RxStreamer#0:0"
|
||||
"\n";
|
||||
// variables to be set by po
|
||||
std::string args, file, format, ant, subdev, ref, wirefmt, streamargs, block_id,
|
||||
block_props;
|
||||
@ -232,53 +309,94 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
po::options_description desc("Allowed options");
|
||||
// clang-format off
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the file to write binary samples to")
|
||||
("format", po::value<std::string>(&format)->default_value("sc16"), "File sample format: sc16, fc32, or fc64")
|
||||
("duration", po::value<double>(&total_time)->default_value(0), "total number of seconds to receive")
|
||||
("nsamps", po::value<size_t>(&total_num_samps)->default_value(0), "total number of samples to receive")
|
||||
("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer")
|
||||
("spp", po::value<size_t>(&spp), "samples per packet (on FPGA and wire)")
|
||||
("streamargs", po::value<std::string>(&streamargs)->default_value(""), "stream args")
|
||||
("progress", "periodically display short-term bandwidth")
|
||||
("stats", "show average bandwidth on exit")
|
||||
("sizemap", "track packet size and display breakdown on exit")
|
||||
("null", "run without writing to file")
|
||||
("continue", "don't abort on a bad packet")
|
||||
|
||||
("args", po::value<std::string>(&args)->default_value(""), "USRP device address args")
|
||||
("setup", po::value<double>(&setup_time)->default_value(1.0), "seconds of setup time")
|
||||
|
||||
("radio-id", po::value<size_t>(&radio_id)->default_value(0), "Radio ID to use (0 or 1).")
|
||||
("radio-chan", po::value<size_t>(&radio_chan)->default_value(0), "Radio channel")
|
||||
("rate", po::value<double>(&rate)->default_value(1e6), "RX rate of the radio block")
|
||||
("freq", po::value<double>(&freq)->default_value(0.0), "RF center frequency in Hz")
|
||||
("lo-offset", po::value<double>(&lo_offset), "Offset for frontend LO in Hz (optional)")
|
||||
("gain", po::value<double>(&gain), "gain for the RF chain")
|
||||
("ant", po::value<std::string>(&ant), "antenna selection")
|
||||
("bw", po::value<double>(&bw), "analog frontend filter bandwidth in Hz")
|
||||
("ref", po::value<std::string>(&ref), "reference source (internal, external, mimo)")
|
||||
("skip-lo", "skip checking LO lock status")
|
||||
("int-n", "tune USRP with integer-N tuning")
|
||||
|
||||
("block-id", po::value<std::string>(&block_id), "If block ID is specified, this block is inserted between radio and host.")
|
||||
("block-port", po::value<size_t>(&block_port)->default_value(0), "If block ID is specified, this block is inserted between radio and host.")
|
||||
("block-props", po::value<std::string>(&block_props), "These are passed straight to the block as properties (see set_properties()).")
|
||||
("help", "Show this help message and exit.")
|
||||
("file", po::value<std::string>(&file)->default_value("usrp_samples.dat"), "Name of the raw binary "
|
||||
"file to which received data will be written.")
|
||||
("format", po::value<std::string>(&format)->default_value("sc16"), "Specifies the data format of the "
|
||||
"file. The data will be written as interleaved IQ samples in one of the following numeric formats: 'double' "
|
||||
"(64-bit float, fc64), 'float' (32-bit float, fc32), or 'short' (16-bit integer, sc16, scaled to int16 range "
|
||||
"-32768 to 32767)."
|
||||
"\nChoosing 'short' as the file format matches the sc16 over-the-wire format and is usually sufficient. Using "
|
||||
"'float' or 'double' does not improve precision, but may be more convenient for post-processing or for "
|
||||
"compatibility with certain analysis tools.")
|
||||
("duration", po::value<double>(&total_time)->default_value(0), "Total number of seconds to receive. "
|
||||
"The program stops when this number is reached.")
|
||||
("nsamps", po::value<size_t>(&total_num_samps)->default_value(0), "Total number of samples to "
|
||||
"receive. The program stops when this number is reached.")
|
||||
("spb", po::value<size_t>(&spb)->default_value(10000), "Size of the host data buffer that is "
|
||||
"allocated for each Rx channel."
|
||||
"\nLarger values may help to improve throughput.")
|
||||
("spp", po::value<size_t>(&spp), "Specifies the number of samples per packet sent from the FPGA to "
|
||||
"the host. Adjusting this value can affect streaming efficiency and packetization behavior.")
|
||||
("streamargs", po::value<std::string>(&streamargs)->default_value(""), "Specifies additional "
|
||||
"key-value arguments for configuring the RX streamer. These options allow advanced control over streaming "
|
||||
"behavior, such as buffer sizes or data formats.")
|
||||
("progress", "Periodically display the estimated short-term USRP device to host streaming rate in "
|
||||
"samples per second.")
|
||||
("stats", "Show the total number of samples received and the elapsed time when the program exits.")
|
||||
("sizemap", "Track and display a breakdown of received packet sizes on exit. This helps diagnose "
|
||||
"streaming performance and packetization issues.")
|
||||
("null", "Run without writing to file.")
|
||||
("continue", "Continue streaming even if a bad packet is received.")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "Single USRP device selection and "
|
||||
"configuration arguments."
|
||||
"\nSpecify key-value pairs (e.g., addr, serial, type, master_clock_rate) separated by commas."
|
||||
"\nSee the UHD manual for model-specific options."
|
||||
"\nExamples:"
|
||||
"\n --args \"addr=192.168.10.2\""
|
||||
"\n --args \"addr=192.168.10.2,master_clock_rate=200e6\""
|
||||
"\nIf not specified, UHD connects to the first available device.")
|
||||
("setup", po::value<double>(&setup_time)->default_value(1.0), "Sets the amount of time (in seconds) "
|
||||
"the program waits for hardware locks (e.g. LO) to ensure the device is properly synchronized before starting "
|
||||
"reception.")
|
||||
("radio-id", po::value<size_t>(&radio_id)->default_value(0), "Specifies the RFNoC radio block index "
|
||||
"to use for reception. On devices with multiple radio blocks, this argument selects which RF frontend (e.g., "
|
||||
"0 for the first radio, 1 for the second) is addressed for streaming.")
|
||||
("radio-chan", po::value<size_t>(&radio_chan)->default_value(0), "Selects the channel index within "
|
||||
"the chosen RFNoC radio block for data acquisition. This determines which physical receive channel (e.g., 0 "
|
||||
"for the first channel, 1 for the second) is used for streaming.")
|
||||
("rate", po::value<double>(&rate)->default_value(1e6), "RX sample rate in samples/second. Note that "
|
||||
"each USRP device only supports a set of discrete sample rates, which depend on the hardware model and "
|
||||
"configuration. If you request a rate that is not supported, the USRP device will automatically select and "
|
||||
"use the closest available rate.")
|
||||
("freq", po::value<double>(&freq)->default_value(0.0), "RF center frequency in Hz.")
|
||||
("lo-offset", po::value<double>(&lo_offset), "LO offset for the frontend in Hz.")
|
||||
("gain", po::value<double>(&gain), "RX gain for the RF chain in dB.")
|
||||
("ant", po::value<std::string>(&ant), "Antenna port selection string selecting a specific antenna "
|
||||
"port for USRP daughterboards having multiple antenna connectors per RF channel."
|
||||
"\nExample: --ant \"TX/RX\"")
|
||||
("bw", po::value<double>(&bw), "Sets the analog frontend filter bandwidth for the RX path in Hz. Not "
|
||||
"all USRP devices support programmable bandwidth; if an unsupported value is requested, the device will use "
|
||||
"the nearest supported bandwidth instead.")
|
||||
("ref", po::value<std::string>(&ref), "Sets the source for the frequency reference. Available values "
|
||||
"depend on the USRP model. Typical values are 'internal', 'external', 'mimo', and 'gpsdo'.")
|
||||
("skip-lo", "Skip checking and waiting for hardware locks (LO, reference, MIMO synchronization) "
|
||||
"before starting reception.")
|
||||
("int-n", "Use integer-N tuning for USRP RF synthesizers. With this mode, the LO can only be tuned in "
|
||||
"discrete steps, which are integer multiples of the reference frequency. This mode can improve phase noise "
|
||||
"and spurious performance at the cost of coarser frequency resolution.")
|
||||
("block-id", po::value<std::string>(&block_id), "Specifies an RFNoC block to insert between the radio "
|
||||
"and host (e.g., if your FPGA image includes a routable FFT or FIR block, use the RFNoC block identifiers "
|
||||
"\"0/FFT0\" or \"0/FIR0\" to address them)."
|
||||
"\nThe specified block must be present in the FPGA image; a list of available RFNoC blocks can be obtained "
|
||||
"using the uhd_usrp_probe command.")
|
||||
("block-port", po::value<size_t>(&block_port)->default_value(0), "Selects which input port of the "
|
||||
"RFNoC block specified by --block-id receives data from the radio block. Use the port index (e.g., 0 or 1) to "
|
||||
"choose the connection point.")
|
||||
("block-props", po::value<std::string>(&block_props), "Sets RFNoC-specific key-value properties, "
|
||||
"which are passed directly to the block specified by --block-id. For RFNoC blocks shipped with UHD, "
|
||||
"block-specific options are documented in the UHD manual.")
|
||||
;
|
||||
// clang-format on
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
// print the help message
|
||||
if (vm.count("help")) {
|
||||
std::cout << "UHD/RFNoC RX samples to file " << desc << std::endl;
|
||||
std::cout << std::endl
|
||||
<< "This application streams data from a single channel of a USRP "
|
||||
"device to a file.\n"
|
||||
<< std::endl;
|
||||
std::cout << program_doc << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
return ~0;
|
||||
}
|
||||
po::notify(vm); // only called if --help was not requested
|
||||
|
||||
bool bw_summary = vm.count("progress") > 0;
|
||||
bool stats = vm.count("stats") > 0;
|
||||
@ -305,7 +423,7 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
std::cout << "Creating the RFNoC graph with args: " << args << std::endl;
|
||||
auto graph = uhd::rfnoc::rfnoc_graph::make(args);
|
||||
|
||||
// Create handle for radio object
|
||||
// Create handle for radio object (e.g. 0/Radio#0)
|
||||
uhd::rfnoc::block_id_t radio_ctrl_id(0, "Radio", radio_id);
|
||||
// This next line will fail if the radio is not actually available
|
||||
auto radio_ctrl = graph->get_block<uhd::rfnoc::radio_control>(radio_ctrl_id);
|
||||
@ -401,28 +519,6 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
radio_ctrl->set_rx_antenna(ant, radio_chan);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t(1000 * setup_time)));
|
||||
|
||||
// check Ref and LO Lock detect
|
||||
if (not vm.count("skip-lo")) {
|
||||
check_locked_sensor(
|
||||
radio_ctrl->get_rx_sensor_names(radio_chan),
|
||||
"lo_locked",
|
||||
[&](const std::string& sensor_name) {
|
||||
return radio_ctrl->get_rx_sensor(sensor_name, radio_chan);
|
||||
},
|
||||
setup_time);
|
||||
if (ref == "external") {
|
||||
check_locked_sensor(
|
||||
graph->get_mb_controller(0)->get_sensor_names(),
|
||||
"ref_locked",
|
||||
[&](const std::string& sensor_name) {
|
||||
return graph->get_mb_controller(0)->get_sensor(sensor_name);
|
||||
},
|
||||
setup_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.count("spp")) {
|
||||
std::cout << "Requesting samples per packet of: " << spp << std::endl;
|
||||
radio_ctrl->set_property<int>("spp", spp, radio_chan);
|
||||
@ -496,6 +592,28 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
|
||||
std::cout << "Actual RX Rate: " << (rate / 1e6) << " Msps..." << std::endl
|
||||
<< std::endl;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(int64_t(1000 * setup_time)));
|
||||
|
||||
// check Ref and LO Lock detect
|
||||
if (not vm.count("skip-lo")) {
|
||||
check_locked_sensor(
|
||||
radio_ctrl->get_rx_sensor_names(radio_chan),
|
||||
"lo_locked",
|
||||
[&](const std::string& sensor_name) {
|
||||
return radio_ctrl->get_rx_sensor(sensor_name, radio_chan);
|
||||
},
|
||||
setup_time);
|
||||
if (ref == "external") {
|
||||
check_locked_sensor(
|
||||
graph->get_mb_controller(0)->get_sensor_names(),
|
||||
"ref_locked",
|
||||
[&](const std::string& sensor_name) {
|
||||
return graph->get_mb_controller(0)->get_sensor(sensor_name);
|
||||
},
|
||||
setup_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (vm.count("block-props")) {
|
||||
std::cout << "Setting block properties to: " << block_props << std::endl;
|
||||
graph->get_block(uhd::rfnoc::block_id_t(block_id))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user