Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example Applications - Bug fixes and enhancements for tx_waveforms and tx_samples_from_file #707

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 96 additions & 37 deletions host/examples/tx_samples_from_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/thread.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <boost/program_options.hpp>
#include <chrono>
Expand All @@ -34,6 +35,7 @@ void send_from_file(
md.start_of_burst = false;
md.end_of_burst = false;
std::vector<samp_type> buff(samps_per_buff);
std::vector<samp_type*> buffs(tx_stream->get_num_channels(), &buff.front());
std::ifstream infile(file.c_str(), std::ifstream::binary);

// loop until the entire file has been read
Expand All @@ -44,7 +46,7 @@ void send_from_file(

md.end_of_burst = infile.eof();

const size_t samples_sent = tx_stream->send(&buff.front(), num_tx_samps, md);
const size_t samples_sent = tx_stream->send(buffs, num_tx_samps, md);
if (samples_sent != num_tx_samps) {
UHD_LOG_ERROR("TX-STREAM",
"The tx_stream timed out sending " << num_tx_samps << " samples ("
Expand All @@ -59,9 +61,9 @@ void send_from_file(
int UHD_SAFE_MAIN(int argc, char* argv[])
{
// variables to be set by po
std::string args, file, type, ant, subdev, ref, wirefmt, channel;
size_t spb;
double rate, freq, gain, bw, delay, lo_offset;
std::string args, file, type, ant, subdev, ref, wirefmt, channels;
size_t spb, single_channel;
double rate, freq, gain, power, bw, delay, lo_offset;

// setup the program options
po::options_description desc("Allowed options");
Expand All @@ -77,13 +79,15 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
("lo-offset", po::value<double>(&lo_offset)->default_value(0.0),
"Offset for frontend LO in Hz (optional)")
("gain", po::value<double>(&gain), "gain for the RF chain")
("power", po::value<double>(&power), "transmit power")
("ant", po::value<std::string>(&ant), "antenna selection")
("subdev", po::value<std::string>(&subdev), "subdevice specification")
("bw", po::value<double>(&bw), "analog frontend filter bandwidth in Hz")
("ref", po::value<std::string>(&ref), "clock reference (internal, external, mimo, gpsdo)")
("wirefmt", po::value<std::string>(&wirefmt)->default_value("sc16"), "wire format (sc8 or sc16)")
("delay", po::value<double>(&delay)->default_value(0.0), "specify a delay between repeated transmission of file (in seconds)")
("channel", po::value<std::string>(&channel)->default_value("0"), "which channel to use")
("channel", po::value<size_t>(&single_channel), "which channel to use")
("channels", po::value<std::string>(&channels), "which channels to use (specify \"0\", \"1\", \"0,1\", etc)")
("repeat", "repeatedly transmit file")
("int-n", "tune USRP with integer-n tuning")
;
Expand All @@ -106,6 +110,30 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
<< std::endl;
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);

// Channels
std::vector<size_t> channel_nums;
std::vector<std::string> channels_split;
if (vm.count("channel")) {
if (vm.count("channels")) {
std::cout << "ERROR: Cannot specify 'channel' and 'channels'!" << std::endl;
return EXIT_FAILURE;
}
if (single_channel >= usrp->get_tx_num_channels())
throw std::runtime_error("Invalid channel specified.");
channel_nums.push_back(single_channel);
} else {
// Provide default
if (!vm.count("channels"))
channels = "0";
// Split string into 1 or more channels
boost::split(channels_split, channels, boost::is_any_of("\"',"));
for (std::string channel : channels_split) {
if (boost::lexical_cast<size_t>(channel) >= usrp->get_tx_num_channels())
throw std::runtime_error("Invalid channel(s) specified.");
channel_nums.push_back(boost::lexical_cast<size_t>(channel));
}
}

// Lock mboard clocks
if (vm.count("ref")) {
usrp->set_clock_source(ref);
Expand All @@ -123,10 +151,13 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
return ~0;
}
std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate / 1e6) << std::endl;
usrp->set_tx_rate(rate);
std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate() / 1e6)
<< std::endl
<< std::endl;
for (std::size_t channel : channel_nums) {
usrp->set_tx_rate(rate, channel);
std::cout << boost::format("Actual TX Rate: %f Msps...")
% (usrp->get_tx_rate(channel) / 1e6)
<< std::endl
<< std::endl;
}

// set the center frequency
if (not vm.count("freq")) {
Expand All @@ -140,47 +171,76 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
tune_request = uhd::tune_request_t(freq, lo_offset);
if (vm.count("int-n"))
tune_request.args = uhd::device_addr_t("mode_n=integer");
usrp->set_tx_freq(tune_request);
std::cout << boost::format("Actual TX Freq: %f MHz...") % (usrp->get_tx_freq() / 1e6)
<< std::endl
<< std::endl;

// set the rf gain
if (vm.count("gain")) {
std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl;
usrp->set_tx_gain(gain);
std::cout << boost::format("Actual TX Gain: %f dB...") % usrp->get_tx_gain()
for (std::size_t channel : channel_nums) {
usrp->set_tx_freq(tune_request, channel);
std::cout << boost::format("Actual TX Freq: %f MHz...")
% (usrp->get_tx_freq(channel) / 1e6)
<< std::endl
<< std::endl;
}

// set the rf gain
if (vm.count("power")) {
for (std::size_t channel : channel_nums) {
if (!usrp->has_tx_power_reference(channel)) {
std::cout << "ERROR: USRP does not have a reference power API on channel "
<< channel << "!" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Setting TX output power: " << power << " dBm..." << std::endl;
usrp->set_tx_power_reference(power, channel);
std::cout << "Actual TX output power: "
<< usrp->get_tx_power_reference(channel) << " dBm..." << std::endl;
}

if (vm.count("gain")) {
std::cout << "WARNING: If you specify both --power and --gain, "
" the latter will be ignored."
<< std::endl;
}
} else if (vm.count("gain")) {
for (std::size_t channel : channel_nums) {
std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl;
usrp->set_tx_gain(gain, channel);
std::cout << boost::format("Actual TX Gain: %f dB...")
% usrp->get_tx_gain(channel)
<< std::endl
<< std::endl;
}
}

// set the analog frontend filter bandwidth
if (vm.count("bw")) {
std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % (bw / 1e6)
<< std::endl;
usrp->set_tx_bandwidth(bw);
std::cout << boost::format("Actual TX Bandwidth: %f MHz...")
% (usrp->get_tx_bandwidth() / 1e6)
<< std::endl
<< std::endl;
for (std::size_t channel : channel_nums) {
usrp->set_tx_bandwidth(bw, channel);
std::cout << boost::format("Actual TX Bandwidth: %f MHz...")
% (usrp->get_tx_bandwidth(channel) / 1e6)
<< std::endl
<< std::endl;
}
}

// set the antenna
if (vm.count("ant"))
usrp->set_tx_antenna(ant);

if (vm.count("ant")) {
for (std::size_t channel : channel_nums)
usrp->set_tx_antenna(ant, channel);
}
// allow for some setup time:
std::this_thread::sleep_for(std::chrono::seconds(1));

// Check Ref and LO Lock detect
std::vector<std::string> sensor_names;
sensor_names = usrp->get_tx_sensor_names(0);
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);
std::cout << boost::format("Checking TX: %s ...") % lo_locked.to_pp_string()
<< std::endl;
UHD_ASSERT_THROW(lo_locked.to_bool());
for (std::size_t channel : channel_nums) {
sensor_names = usrp->get_tx_sensor_names(channel);
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", channel);
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);
if ((ref == "mimo")
Expand Down Expand Up @@ -208,15 +268,14 @@ int UHD_SAFE_MAIN(int argc, char* argv[])

// create a transmit streamer
std::string cpu_format;
std::vector<size_t> channel_nums;
if (type == "double")
cpu_format = "fc64";
else if (type == "float")
cpu_format = "fc32";
else if (type == "short")
cpu_format = "sc16";

uhd::stream_args_t stream_args(cpu_format, wirefmt);
channel_nums.push_back(boost::lexical_cast<size_t>(channel));
stream_args.channels = channel_nums;
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);

Expand All @@ -240,4 +299,4 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
std::cout << std::endl << "Done!" << std::endl << std::endl;

return EXIT_SUCCESS;
}
}
44 changes: 24 additions & 20 deletions host/examples/tx_waveforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,13 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
return ~0;
}
std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate / 1e6) << std::endl;
usrp->set_tx_rate(rate);
std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate() / 1e6)
<< std::endl
<< std::endl;
for (std::size_t channel : channel_nums) {
usrp->set_tx_rate(rate, channel);
std::cout << boost::format("Actual TX Rate: %f Msps...")
% (usrp->get_tx_rate(channel) / 1e6)
<< std::endl
<< std::endl;
}

// set the center frequency
if (not vm.count("freq")) {
Expand All @@ -131,7 +134,7 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
// for the const wave, set the wave freq for small samples per period
if (wave_freq == 0) {
if (wave_type == "CONST") {
wave_freq = usrp->get_tx_rate() / 2;
wave_freq = usrp->get_tx_rate(channel_nums.front()) / 2;
} else {
throw std::runtime_error(
"wave freq cannot be 0 with wave type other than CONST");
Expand All @@ -140,34 +143,35 @@ int UHD_SAFE_MAIN(int argc, char* argv[])

// pre-compute the waveform values
const wave_table_class wave_table(wave_type, ampl);
const size_t step = std::lround(wave_freq / usrp->get_tx_rate() * wave_table_len);
size_t index = 0;
const size_t step =
std::lround(wave_freq / usrp->get_tx_rate(channel_nums.front()) * wave_table_len);
size_t index = 0;

for (size_t ch = 0; ch < channel_nums.size(); ch++) {
for (std::size_t channel : channel_nums) {
std::cout << boost::format("Setting TX Freq: %f MHz...") % (freq / 1e6)
<< std::endl;
std::cout << boost::format("Setting TX LO Offset: %f MHz...") % (lo_offset / 1e6)
<< std::endl;
uhd::tune_request_t tune_request(freq, lo_offset);
if (vm.count("int-n"))
tune_request.args = uhd::device_addr_t("mode_n=integer");
usrp->set_tx_freq(tune_request, channel_nums[ch]);
usrp->set_tx_freq(tune_request, channel);
std::cout << boost::format("Actual TX Freq: %f MHz...")
% (usrp->get_tx_freq(channel_nums[ch]) / 1e6)
% (usrp->get_tx_freq(channel) / 1e6)
<< std::endl
<< std::endl;

// set the rf gain
if (vm.count("power")) {
if (!usrp->has_tx_power_reference(ch)) {
if (!usrp->has_tx_power_reference(channel)) {
std::cout << "ERROR: USRP does not have a reference power API on channel "
<< ch << "!" << std::endl;
<< channel << "!" << std::endl;
return EXIT_FAILURE;
}
std::cout << "Setting TX output power: " << power << " dBm..." << std::endl;
usrp->set_tx_power_reference(power - wave_table.get_power(), ch);
usrp->set_tx_power_reference(power - wave_table.get_power(), channel);
std::cout << "Actual TX output power: "
<< usrp->get_tx_power_reference(ch) + wave_table.get_power()
<< usrp->get_tx_power_reference(channel) + wave_table.get_power()
<< " dBm..." << std::endl;
if (vm.count("gain")) {
std::cout << "WARNING: If you specify both --power and --gain, "
Expand All @@ -176,9 +180,9 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
}
} else if (vm.count("gain")) {
std::cout << boost::format("Setting TX Gain: %f dB...") % gain << std::endl;
usrp->set_tx_gain(gain, channel_nums[ch]);
usrp->set_tx_gain(gain, channel);
std::cout << boost::format("Actual TX Gain: %f dB...")
% usrp->get_tx_gain(channel_nums[ch])
% usrp->get_tx_gain(channel)
<< std::endl
<< std::endl;
}
Expand All @@ -187,16 +191,16 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
if (vm.count("bw")) {
std::cout << boost::format("Setting TX Bandwidth: %f MHz...") % bw
<< std::endl;
usrp->set_tx_bandwidth(bw, channel_nums[ch]);
usrp->set_tx_bandwidth(bw, channel);
std::cout << boost::format("Actual TX Bandwidth: %f MHz...")
% usrp->get_tx_bandwidth(channel_nums[ch])
% usrp->get_tx_bandwidth(channel)
<< std::endl
<< std::endl;
}

// set the antenna
if (vm.count("ant"))
usrp->set_tx_antenna(ant, channel_nums[ch]);
usrp->set_tx_antenna(ant, channel);
}

std::this_thread::sleep_for(std::chrono::seconds(1)); // allow for some setup time
Expand Down Expand Up @@ -327,4 +331,4 @@ int UHD_SAFE_MAIN(int argc, char* argv[])
// finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
return EXIT_SUCCESS;
}
}