summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/examples/benchmark_rx_rate.cpp2
-rw-r--r--host/include/uhd/device.hpp11
-rw-r--r--host/include/uhd/types/metadata.hpp44
-rw-r--r--host/lib/transport/vrt_packet_handler.hpp18
-rw-r--r--host/lib/types.cpp12
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp40
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
7 files changed, 90 insertions, 38 deletions
diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp
index 752facb0d..8fae813cf 100644
--- a/host/examples/benchmark_rx_rate.cpp
+++ b/host/examples/benchmark_rx_rate.cpp
@@ -66,7 +66,7 @@ static inline void test_device(
//handle the error codes
switch(md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
- case uhd::rx_metadata_t::ERROR_CODE_OVERRUN:
+ case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
break;
default:
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp
index ee297ec8a..78bb83c66 100644
--- a/host/include/uhd/device.hpp
+++ b/host/include/uhd/device.hpp
@@ -219,6 +219,17 @@ public:
*/
virtual size_t get_max_recv_samps_per_packet(void) const = 0;
+ /*!
+ * Receive and asynchronous message from the device.
+ * \param async_metadata the metadata to be filled in
+ * \param timeout_ms the timeout in milliseconds to wait for a message
+ * \return true when the async_metadata is valid, false for timeout
+ */
+ virtual bool recv_async_msg(
+ async_metadata_t &async_metadata,
+ size_t timeout_ms = default_recv_timeout_ms
+ ) = 0;
+
};
} //namespace uhd
diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp
index 039196250..43ddf875f 100644
--- a/host/include/uhd/types/metadata.hpp
+++ b/host/include/uhd/types/metadata.hpp
@@ -26,7 +26,7 @@ namespace uhd{
/*!
* RX metadata structure for describing sent IF data.
- * Includes stream ID, time specification, and fragmentation flags.
+ * Includes time specification, fragmentation flags, burst flags, and error codes.
* The receive routines will convert IF data headers into metadata.
*/
struct UHD_API rx_metadata_t{
@@ -62,7 +62,7 @@ namespace uhd{
* - timeout: no packet received, underlying code timed-out
* - late command: a stream command was issued in the past
* - broken chain: expected another stream command
- * - overrun: an internal receive buffer has overrun
+ * - overflow: an internal receive buffer has filled
* - bad packet: the buffer was unrecognizable as a vrt packet
*
* Note: When an overrun occurs in continuous streaming mode,
@@ -74,27 +74,21 @@ namespace uhd{
* - none
* - late command
* - broken chain
- * - overrun
+ * - overflow
*/
enum error_code_t {
ERROR_CODE_NONE = 0x0,
ERROR_CODE_TIMEOUT = 0x1,
ERROR_CODE_LATE_COMMAND = 0x2,
ERROR_CODE_BROKEN_CHAIN = 0x4,
- ERROR_CODE_OVERRUN = 0x8,
+ ERROR_CODE_OVERFLOW = 0x8,
ERROR_CODE_BAD_PACKET = 0xf
} error_code;
-
- /*!
- * The default constructor:
- * Sets the fields to default values (flags set to false).
- */
- rx_metadata_t(void);
};
/*!
* TX metadata structure for describing received IF data.
- * Includes stream ID, time specification, and burst flags.
+ * Includes time specification, and start and stop burst flags.
* The send routines will convert the metadata to IF data headers.
*/
struct UHD_API tx_metadata_t{
@@ -121,6 +115,34 @@ namespace uhd{
tx_metadata_t(void);
};
+ /*!
+ * Async metadata structure for describing transmit related events.
+ */
+ struct UHD_API async_metadata_t{
+ //! The channel number in a mimo configuration
+ size_t channel;
+
+ /*!
+ * Time specification: when the async event occurred.
+ */
+ bool has_time_spec;
+ time_spec_t time_spec;
+
+ /*!
+ * Event codes:
+ * - success: a packet was successfully transmitted
+ * - underflow: an internal send buffer has emptied
+ * - sequence error: packet loss between host and device
+ * - time error: packet had time that was late (or too early)
+ */
+ enum event_code_t {
+ EVENT_CODE_SUCCESS = 0x1,
+ EVENT_CODE_UNDERFLOW = 0x2,
+ EVENT_CODE_SEQ_ERROR = 0x4,
+ EVENT_CODE_TIME_ERROR = 0x8
+ } event_code;
+ };
+
} //namespace uhd
#endif /* INCLUDED_UHD_TYPES_METADATA_HPP */
diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp
index 07ad9115c..3eddcec6d 100644
--- a/host/lib/transport/vrt_packet_handler.hpp
+++ b/host/lib/transport/vrt_packet_handler.hpp
@@ -40,10 +40,10 @@ namespace vrt_packet_handler{
**********************************************************************/
typedef std::vector<uhd::transport::managed_recv_buffer::sptr> managed_recv_buffs_t;
typedef boost::function<bool(managed_recv_buffs_t &)> get_recv_buffs_t;
- typedef boost::function<void(size_t /*which channel*/)> handle_overrun_t;
+ typedef boost::function<void(size_t /*which channel*/)> handle_overflow_t;
typedef boost::function<void(const boost::uint32_t *, uhd::transport::vrt::if_packet_info_t &)> vrt_unpacker_t;
- static inline void handle_overrun_nop(size_t){}
+ static inline void handle_overflow_nop(size_t){}
struct recv_state{
//width of the receiver in channels
@@ -75,7 +75,7 @@ namespace vrt_packet_handler{
uhd::rx_metadata_t &metadata,
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
- const handle_overrun_t &handle_overrun,
+ const handle_overflow_t &handle_overflow,
size_t vrt_header_offset_words32
){
//vrt unpack each managed buffer
@@ -99,7 +99,7 @@ namespace vrt_packet_handler{
//extract the context word (we dont know the endianness so mirror the bytes)
boost::uint32_t word0 = vrt_data[0] | uhd::byteswap(vrt_data[0]);
- if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERRUN) handle_overrun(i);
+ if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) handle_overflow(i);
metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf);
//break to exit loop and store metadata below
@@ -142,7 +142,7 @@ namespace vrt_packet_handler{
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
const get_recv_buffs_t &get_recv_buffs,
- const handle_overrun_t &handle_overrun,
+ const handle_overflow_t &handle_overflow,
size_t vrt_header_offset_words32
){
metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE;
@@ -157,7 +157,7 @@ namespace vrt_packet_handler{
try{
_recv1_helper(
state, metadata, tick_rate,
- vrt_unpacker, handle_overrun,
+ vrt_unpacker, handle_overflow,
vrt_header_offset_words32
);
}catch(const std::exception &e){
@@ -216,7 +216,7 @@ namespace vrt_packet_handler{
double tick_rate,
const vrt_unpacker_t &vrt_unpacker,
const get_recv_buffs_t &get_recv_buffs,
- const handle_overrun_t &handle_overrun = &handle_overrun_nop,
+ const handle_overflow_t &handle_overflow = &handle_overflow_nop,
size_t vrt_header_offset_words32 = 0
){
switch(recv_mode){
@@ -233,7 +233,7 @@ namespace vrt_packet_handler{
tick_rate,
vrt_unpacker,
get_recv_buffs,
- handle_overrun,
+ handle_overflow,
vrt_header_offset_words32
);
}
@@ -253,7 +253,7 @@ namespace vrt_packet_handler{
tick_rate,
vrt_unpacker,
get_recv_buffs,
- handle_overrun,
+ handle_overflow,
vrt_header_offset_words32
);
if (num_samps == 0) break; //had a recv timeout or error, break loop
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index fdc435fef..1cfe84832 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -98,18 +98,6 @@ stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode):
/***********************************************************************
* metadata
**********************************************************************/
-rx_metadata_t::rx_metadata_t(void):
- has_time_spec(false),
- time_spec(time_spec_t()),
- more_fragments(false),
- fragment_offset(0),
- start_of_burst(false),
- end_of_burst(false),
- error_code(ERROR_CODE_NONE)
-{
- /* NOP */
-}
-
tx_metadata_t::tx_metadata_t(void):
has_time_spec(false),
time_spec(time_spec_t()),
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index 1947fdf00..455a30b47 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -44,7 +44,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 */
}
@@ -69,6 +70,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;
size_t recv_timeout_ms;
};
@@ -94,18 +96,34 @@ 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 (TODO forward 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){
- std::cerr << "U";
+ const boost::uint32_t *vrt_data = vrt_hdr + if_packet_info.num_header_words32;
+ //extract the context word (we dont know the endianness so mirror the bytes)
+ boost::uint32_t word0 = vrt_data[0] | uhd::byteswap(vrt_data[0]);
+
+ //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 = uhd::async_metadata_t::event_code_t(word0 & 0xf);
+
+ //print the famous U, and push the metadata into the message queue
+ if (metadata.event_code == async_metadata_t::EVENT_CODE_UNDERFLOW) 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;
@@ -157,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(
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index cae1b21d6..2eaf12350 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -235,6 +235,7 @@ public:
uhd::rx_metadata_t &, const uhd::io_type_t &,
uhd::device::recv_mode_t, size_t
);
+ bool recv_async_msg(uhd::async_metadata_t &, size_t);
private:
//device properties interface