Search code examples
c++usrpuhd

How to stream a fixed number of samples from a USRP using UHD


I am trying to stream a fixed/exact number of samples from a USRP X310 device using the UHD library. I have referenced some example code on the UHD GitHub page. I am using a while loop as recommended to stream data into a buffer one packet at a time. My problem is that the last partial packet (see example below) is never received or placed into my buffer and I get the uhd::rx_metadata_t::ERROR_CODE_TIMEOUT error response.

// Instantiate RX Streamer
uhd::stream_args_t streamArgs("fc32");
// Set the number of samples per packet
streamArgs.args["spp"] = "200";
rxStream = usrpDevice->get_rx_stream(streamArgs);
    
// Configure RX Streamer for fixed number of samples
uhd::stream_cmd_t streamCmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
streamCmd.num_samps = 1100;
streamCmd.stream_now = true;
rxStream->issue_stream_cmd(streamCmd);

// Initialize RX metadata structure
uhd::rx_metadata_t md;

// Create buffer to stream samples to
std::vector<std::complex<float>> buff(rxStream->get_max_num_samps()); // buff size = 200

size_t numAccSamples = 0;

while (numAccSamples < 1100)
{
    size_t numRXSamples = rxStream->recv(&buff.front(), buff.size(), md);
    
    // Handle streaming error codes
    switch (md.error_code)
    {
        // No errors
        case uhd::rx_metadata_t::ERROR_CODE_NONE:
            break;
            
        case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT: // I get this error on the expected last iteration of the while loop
            if (numAccSamples == 0)
            {
                continue;
            }
            throw std::runtime_error("ERROR_CODE_TIMEOUT: Got timeout before all samples received");
            
            default:
                throw std::runtime_error("Got error code " + md.error_code);
        }
        
        // process data here

        numAccSamples += numRXSamples;
    }

For example, if I want to stream 1100 samples and my packet size is set to 200, my while loop will run 5 times successfully and populate my buffer. However, when I enter my while loop for the sixth time (I have 1000/1100 samples), the call to recv() gets a timeout error and the samples are not passed to my buffer. At this point I haven't streamed all 1100 of my samples.

How can I go about getting my exact number of samples?

Here is a link to the documentation for the recv() call for reference.


Solution

  • After much trial and error, I figured out that this problem comes up because the sample rate parameter has not been set on the USRP. So before trying to stream samples be sure to set the sample rate!

    usrpDevice->set_rx_rate(50e6);
    
    // stream samples