diff options
Diffstat (limited to 'host/lib/usrp/usrp2/io_impl.cpp')
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 430f28390..9e29edd82 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -32,6 +32,8 @@ using namespace uhd::usrp; using namespace uhd::transport; namespace asio = boost::asio; +static const int underflow_flags = async_metadata_t::EVENT_CODE_UNDERFLOW | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET; + /*********************************************************************** * io impl details (internal to this file) * - pirate crew @@ -44,7 +46,8 @@ struct usrp2_impl::io_impl{ io_impl(size_t num_frames, size_t width): packet_handler_recv_state(width), - recv_pirate_booty(alignment_buffer_type::make(num_frames, width)) + recv_pirate_booty(alignment_buffer_type::make(num_frames, width)), + async_msg_fifo(bounded_buffer<async_metadata_t>::make(100/*messages deep*/)) { /* NOP */ } @@ -55,9 +58,9 @@ struct usrp2_impl::io_impl{ recv_pirate_crew.join_all(); } - bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs){ + bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, size_t timeout_ms){ boost::this_thread::disable_interruption di; //disable because the wait can throw - return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(100)); + return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(timeout_ms)); } //state management for the vrt packet handler code @@ -69,6 +72,7 @@ struct usrp2_impl::io_impl{ boost::thread_group recv_pirate_crew; bool recv_pirate_crew_raiding; alignment_buffer_type::sptr recv_pirate_booty; + bounded_buffer<async_metadata_t>::sptr async_msg_fifo; }; /*********************************************************************** @@ -93,12 +97,31 @@ void usrp2_impl::io_impl::recv_pirate_loop( //extract the vrt header packet info vrt::if_packet_info_t if_packet_info; if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); - vrt::if_hdr_unpack_be(buff->cast<const boost::uint32_t *>(), if_packet_info); + const boost::uint32_t *vrt_hdr = buff->cast<const boost::uint32_t *>(); + vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); + + //handle a tx async report message + if (if_packet_info.sid == 1 and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ + + //fill in the async metadata + async_metadata_t metadata; + metadata.channel = index; + metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; + metadata.time_spec = time_spec_t( + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq() + ); + metadata.event_code = vrt_packet_handler::get_context_code<async_metadata_t::event_code_t>(vrt_hdr, if_packet_info); + + //print the famous U, and push the metadata into the message queue + if (metadata.event_code & underflow_flags) std::cerr << "U"; + async_msg_fifo->push_with_pop_on_full(metadata); + continue; + } //handle the packet count / sequence number if (if_packet_info.packet_count != next_packet_seq){ //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16; - std::cerr << "O"; //report overrun (drops in the kernel) + std::cerr << "O"; //report overflow (drops in the kernel) } next_packet_seq = (if_packet_info.packet_count+1)%16; @@ -121,11 +144,13 @@ void usrp2_impl::io_impl::recv_pirate_loop( **********************************************************************/ void usrp2_impl::io_init(void){ //send a small data packet so the usrp2 knows the udp source port - for(size_t i = 0; i < _data_transports.size(); i++){ - managed_send_buffer::sptr send_buff = _data_transports[i]->get_send_buff(); - boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); - memcpy(send_buff->cast<void*>(), &data, sizeof(data)); + BOOST_FOREACH(zero_copy_if::sptr data_transport, _data_transports){ + managed_send_buffer::sptr send_buff = data_transport->get_send_buff(); + static const boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); + std::memcpy(send_buff->cast<void*>(), &data, sizeof(data)); send_buff->commit(sizeof(data)); + //drain the recv buffers (may have junk) + while (data_transport->get_recv_buff().get()); } //the number of recv frames is the number for the first transport @@ -150,6 +175,18 @@ void usrp2_impl::io_init(void){ } /*********************************************************************** + * Async Data + **********************************************************************/ +bool usrp2_impl::recv_async_msg( + async_metadata_t &async_metadata, size_t timeout_ms +){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + return _io_impl->async_msg_fifo->pop_with_timed_wait( + async_metadata, boost::posix_time::milliseconds(timeout_ms) + ); +} + +/*********************************************************************** * Send Data **********************************************************************/ bool get_send_buffs( @@ -164,10 +201,8 @@ bool get_send_buffs( } size_t usrp2_impl::send( - const std::vector<const void *> &buffs, - size_t num_samps, - const tx_metadata_t &metadata, - const io_type_t &io_type, + const std::vector<const void *> &buffs, size_t num_samps, + const tx_metadata_t &metadata, const io_type_t &io_type, send_mode_t send_mode ){ return vrt_packet_handler::send( @@ -186,11 +221,9 @@ size_t usrp2_impl::send( * Receive Data **********************************************************************/ size_t usrp2_impl::recv( - const std::vector<void *> &buffs, - size_t num_samps, - rx_metadata_t &metadata, - const io_type_t &io_type, - recv_mode_t recv_mode + const std::vector<void *> &buffs, size_t num_samps, + rx_metadata_t &metadata, const io_type_t &io_type, + recv_mode_t recv_mode, size_t timeout_ms ){ return vrt_packet_handler::recv( _io_impl->packet_handler_recv_state, //last state of the recv handler @@ -199,6 +232,6 @@ size_t usrp2_impl::recv( io_type, _io_helper.get_rx_otw_type(), //input and output types to convert _mboards.front()->get_master_clock_freq(), //master clock tick rate uhd::transport::vrt::if_hdr_unpack_be, - boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1) + boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl.get(), _1, timeout_ms) ); } |