I am presently working on a straightforward C++ application for fundamental transmission and reception tasks with a USRP B210. Currently, I can effectively transmit and receive signals using a single subdevice. However, I'm interested in being able to switch antennas dynamically, such as switching between RX2 on subdevice 1 and RX2 on subdevice 2. Is it feasible to switch subdevices while the USRP is operational? I have included the complete code below, wherein I utilize the variable m_Settings.m_nTMAntenna to facilitate real-time antenna changes.
#include <src/sdr/usrpdriver.h>
#define DEBUG false
#define NUM_SAMPS 2^16
#define TXENABLED
USRPDriver::USRPDriver()
{
try
{
usrp = uhd::usrp::multi_usrp::make(std::string(""));
}
catch(...) //const uhd::exception &e
{
int r = QMessageBox::warning(0, tr("Expedite"),
tr("USRP Device Unreachable.\n"
"Continue without Device?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No,
QMessageBox::Cancel | QMessageBox::Escape);
if (r == QMessageBox::Yes) {
m_bDeviceUp = false;
return;
} else if (r == QMessageBox::Cancel) {
abort();
}
}
m_bDeviceUp = true;
moveToThread(&m_Thread);
QObject::connect(&m_Thread,SIGNAL(started()),this,SLOT(RxEventLoop()));
// Lock mboard clocks
usrp->set_clock_source("internal");
// Setting transmitter rate
usrp->set_tx_rate(MIN_SAMP_RATE_USRP);
// Setting receiver rate
usrp->set_rx_rate(MIN_SAMP_RATE_USRP);
// Device stream arguments
uhd::stream_args_t stream_args("fc32");
tx_stream = usrp->get_tx_stream(stream_args);
rx_stream = usrp->get_rx_stream(stream_args);
// Timestamp
usrp->set_time_now(uhd::time_spec_t(0.0));
// Start Rx thread
Start();
}
void
USRPDriver::RxEventLoop()
{
if(m_bDeviceUp){
uhd::rx_metadata_t md;
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.stream_now = true;
stream_cmd.num_samps = NUM_SAMPS;
//std::cout << "Maximum num samps = " << rx_stream->get_max_num_samps() << std::endl;
std::vector<std::complex<float> > fcpxIQ;
fcpxIQ.resize(NUM_SAMPS);
rx_stream->issue_stream_cmd(stream_cmd);
while(true)
{
size_t num_rx_samps = rx_stream->recv(&fcpxIQ[0], NUM_SAMPS, md);
emit ReceiveIQ(fcpxIQ);
}
}
}
void
USRPDriver::UpdateTransceiverSettings(TransceiverSettings Settings)
{
m_Settings = Settings;
Initialize(m_Settings);
}
Moses.
You only need one instance of a MultiUSRP and one instance of the streamer. You can leave the subdev spec to default. If you want to modify here are some examples. You need to tell the streamer which channels you want to receive (for a B210 0,1 or both). See this example on how to set receive channels on streamer (example also supports distribute receive to multiple threads).
Let's get through it step by step. The subdev tells UHD how to map the radios of your device to the channel numbers. In case of the B210 with two channels in each direction you can either keep them as they are, swap them or only enable only one of them, see 3. You disabled the other channel in your example, but that is not necessary.
Once you have the channel mapping you can use this in all radio related calls. If you do not specify a channel UHD assumes either channel 0 (e.g. frequency or gain) or all channels (e.g. rate). If you don't know whether it is one or the other you have to look it up in documentation 4. You can also tell the stream command which channel(s) it should act on. Again, if you don't specify a channel the streamer defaults to channel 0.
Last but not least you have to select the correct antenna. For TX on a B210 there is only the TXRX antenna. For RX you can chose between TXRX (if you don't use this antenna for TX) or RX2. With this you can do up to 2TX and 2RX on a B210.
Regarding your example I would advice to remove setting the subdev_spec completly. You can just stick to the default subdev_spec. For the set calls (antenna, freq, gain, …) make sure you also pass along the channel you want to use (you already have it in your m_settings
. In the default subdev spec channel 0 corresponds to the first radio channel 1 to the second. Also you have to tell the streamer which channel you want to use by using stream_args.channels = {<channel>};
with ` being the one you want to use for TX or RX (the same you use for the set calls) - see 5. You can also use a list of channels. In that case you IQ data will be ordered the way you ordered the channels (another way to do channel swapping).
HTH