The RFNoC Replay block would be a good starting point, if you want to do this all in the FPGA.
On Thu, Jul 18, 2019 at 2:04 PM Marcus Müller via USRP-users < usrp-users@lists.ettus.com> wrote: > At the very benign 20 MS/s, I'd really say your first option is the way > to go. The rest probably won't work very well du to turn on/off > behaviour requiring you to zero pad a bit to flush your TX data chains. > > You can of course also write an RFNoC block to store and generate data > in-FPGA, but really: at 20MS/s just continously stream. Even a bog- > normal Gigabit Ethernet card has plenty enough bandwidth to do that. I > doubt sending a sequence from RAM will occupy much CPU on your host PC. > > Best regards, > Marcus > > On Thu, 2019-07-18 at 22:58 +0200, Cédric Hannotier via USRP-users > wrote: > > Dear all, > > > > I would like to periodically send a frame with an USRP X310 (frame > > length: 320 samples, rate: 20 MS/s, period: 1-500 ms). However, I > > struggle to find the best way to implement it. What I have tried so > > far: > > > > 1. Append zeros to the frame to reach the expected period. > > However, > > this consumes too much bandwidth due to the zeros. > > > > 2. Use tx_streamer->send() with a tx_metadata_t.time_spec and > > tx_streamer->recv_async_msg(). Using that, only the frame is sent, > > saving most of the bandwidth. However, with small periods, it tends > > to > > print some 'L'. > > > > 3. Buffer a batch of send request on the USRP, then wait a > > specific > > time (using eg. recv_async_msg() until the returned metadata > > contains > > the penultimate time_spec (I expect that the time_spec returned is > > the > > one specified in the send metadata)) and redo. The issue is that I > > was > > not able to find the buffer size (is it related to the > > tx_streamer->get_max_num_samps()?). I would like to fill the buffer > > without overflow. > > > > I was hoping that I could save the frame in an USRP's memory, and > > then > > ask it to periodically send the frame with a specific period. Is it > > possible? > > > > Here is an example of (2): > > > > template <typename samp_type> > > void send_from_file(const uhd::usrp::multi_usrp::sptr &usrp, > > uhd::tx_streamer::sptr tx_stream, const > > std::string& > > file, > > const double period) > > { > > size_t data_size = get_file_size<samp_type>(file); > > std::ifstream infile(file, std::ifstream::binary); > > std::vector<samp_type> buff(data_size); > > infile.read(reinterpret_cast<char*>(buff.data()), > > (std::streamsize)(buff.size()*sizeof(samp_type))); > > infile.close(); > > size_t num_tx_samps = buff.size(); > > std::cout << file << " " << buff[0] << " " << num_tx_samps << > > std::endl; > > > > uhd::tx_metadata_t md; > > md.start_of_burst = true; > > md.end_of_burst = true; > > md.has_time_spec = true; > > md.time_spec = usrp->get_time_last_pps()+5.; > > double timeout = md.time_spec.get_real_secs(); > > uhd::async_metadata_t md_status; > > > > while (not stop_signal_called) { > > tx_stream->send(&buff.front(), num_tx_samps, md); > > if (tx_stream->recv_async_msg(md_status, timeout)) { > > if (md_status.event_code != > > uhd::async_metadata_t::event_code_t::EVENT_CODE_BURST_ACK) { > > std::cerr << "Error: " << md_status.event_code > > << std::endl; > > exit(EXIT_FAILURE); > > } > > } else { > > std::cerr << "timeout before sent" << std::endl; > > exit(EXIT_FAILURE); > > } > > > > timeout = 0.1; > > md.time_spec += period; > > } > > } > > > > > > > > Best Regards, > > Cédric > > > > _______________________________________________ > > USRP-users mailing list > > USRP-users@lists.ettus.com > > http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com > > > _______________________________________________ > USRP-users mailing list > USRP-users@lists.ettus.com > http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com >
_______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com