diff options
-rw-r--r-- | firmware/microblaze/apps/txrx.c | 4 | ||||
-rw-r--r-- | host/examples/rx_timed_samples.cpp | 5 | ||||
-rw-r--r-- | host/include/uhd/device.hpp | 1 | ||||
-rw-r--r-- | host/include/uhd/types/metadata.hpp | 60 | ||||
-rw-r--r-- | host/include/uhd/types/stream_cmd.hpp | 32 | ||||
-rw-r--r-- | host/lib/types.cpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 30 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 3 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 1 |
10 files changed, 117 insertions, 33 deletions
diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 39a503091..555dd4dd5 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -385,7 +385,7 @@ void handle_udp_ctrl_packet( issue_stream_command( (chain)? streaming_items_per_frame : num_samps, //nsamps (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now - chain, //chain + (ctrl_data_in->data.stream_cmd.chain == 0)? chain : true, //chain ctrl_data_in->data.stream_cmd.secs, ctrl_data_in->data.stream_cmd.ticks, false @@ -398,7 +398,7 @@ void handle_udp_ctrl_packet( issue_stream_command( (chain)? streaming_items_per_frame : num_samps, //nsamps true, //now - chain, //chain + (ctrl_data_in->data.stream_cmd.chain == 0)? chain : true, //chain 0, 0, //time does not matter false ); diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 58b5af9da..1292d9b27 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -67,11 +67,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << std::endl; std::cout << boost::format("Begin streaming %u samples, %d seconds in the future...") % total_num_samps % seconds_in_future << std::endl; - uhd::stream_cmd_t stream_cmd; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; stream_cmd.stream_now = false; stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); - stream_cmd.continuous = false; - stream_cmd.num_samps = total_num_samps; sdev->issue_stream_cmd(stream_cmd); //loop until total number of samples reached diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 4d4196d98..bf7e0753d 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -112,6 +112,7 @@ public: * and will flag the metadata to show that this is a fragment. * The next call to receive, after the remainder becomes exahausted, * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. * * This is a blocking call and will not return until the number * of samples returned have been written into the buffer. diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 6e93040d9..20f483bed 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -29,11 +29,45 @@ namespace uhd{ * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ - boost::uint32_t stream_id; - time_spec_t time_spec; + /*! + * Stream IDs may be used to identify source DSP units. + * --Not currently used in any known device implementation.-- + */ bool has_stream_id; + boost::uint32_t stream_id; + + /*! + * Time specification: + * Set from timestamps on incoming data when provided. + */ bool has_time_spec; - bool is_fragment; + time_spec_t time_spec; + + /*! + * Fragmentation flag and offset: + * Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly + * More fragments is true when the input buffer has insufficient size to fit + * an entire received packet. More fragments will be false for the last fragment. + * The fragment offset is the sample number at the start of the receive buffer. + * For non-fragmented receives, the fragment offset should always be zero. + */ + bool more_fragments; + size_t fragment_offset; + + /*! + * Burst flags: + * Start of burst will be true for the first packet in the chain. + * End of burst will be true for the last packet in the chain. + * --Not currently used in any known device implementation.-- + */ + //bool start_of_burst; + //bool end_of_burst; + + /*! + * Error conditions (TODO): + * Previous packets dropped? + * Timed-out on receive? + */ //default constructor rx_metadata_t(void); @@ -45,10 +79,26 @@ namespace uhd{ * The send routines will convert the metadata to IF data headers. */ struct UHD_API tx_metadata_t{ - boost::uint32_t stream_id; - time_spec_t time_spec; + /*! + * Stream IDs may be used to identify destination DSP units. + * --Not currently used in any known device implementation.-- + */ bool has_stream_id; + boost::uint32_t stream_id; + + /*! + * Time specification: + * Set has time spec to false to perform a send "now". + * Or, set to true, and fill in time spec for a send "at". + */ bool has_time_spec; + time_spec_t time_spec; + + /*! + * Burst flags: + * Set start of burst to true for the first packet in the chain. + * Set end of burst to true for the last packet in the chain. + */ bool start_of_burst; bool end_of_burst; diff --git a/host/include/uhd/types/stream_cmd.hpp b/host/include/uhd/types/stream_cmd.hpp index 97a6b73ce..ff063af29 100644 --- a/host/include/uhd/types/stream_cmd.hpp +++ b/host/include/uhd/types/stream_cmd.hpp @@ -31,24 +31,32 @@ namespace uhd{ * Granular control over what the device streams to the host can be * achieved through submission of multiple (carefully-crafted) commands. * - * The stream_now parameter controls when the stream begins. + * The mode parameter controls how streaming is issued to the device: + * * "Start continuous" tells the device to stream samples indefinitely. + * * "Stop continuous" tells the device to end continuous streaming. + * * "Num samps and done" tells the device to stream num samps and + * to not expect a future stream command for contiguous samples. + * * "Num samps and more" tells the device to stream num samps and + * to expect a future stream command for contiguous samples. + * + * The stream now parameter controls when the stream begins. * When true, the device will begin streaming ASAP. When false, * the device will begin streaming at a time specified by time_spec. - * - * The continuous parameter controls the number of samples received. - * When true, the device continues streaming indefinitely. When false, - * the device will stream the number of samples specified by num_samps. - * - * Standard usage case: - * To start continuous streaming, set stream_now to true and continuous to true. - * To end continuous streaming, set stream_now to true and continuous to false. */ struct UHD_API stream_cmd_t{ + + enum stream_mode_t { + STREAM_MODE_START_CONTINUOUS = 'a', + STREAM_MODE_STOP_CONTINUOUS = 'o', + STREAM_MODE_NUM_SAMPS_AND_DONE = 'd', + STREAM_MODE_NUM_SAMPS_AND_MORE = 'm' + } stream_mode; + size_t num_samps; + bool stream_now; time_spec_t time_spec; - bool continuous; - size_t num_samps; - stream_cmd_t(void); + + stream_cmd_t(const stream_mode_t &stream_mode); }; } //namespace uhd diff --git a/host/lib/types.cpp b/host/lib/types.cpp index bf9f8b895..d87238161 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -71,9 +71,9 @@ clock_config_t::clock_config_t(void){ /*********************************************************************** * stream command **********************************************************************/ -stream_cmd_t::stream_cmd_t(void){ +stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode_){ + stream_mode = stream_mode_; stream_now = true; - continuous = false; num_samps = 0; } @@ -85,7 +85,8 @@ rx_metadata_t::rx_metadata_t(void){ has_stream_id = false; time_spec = time_spec_t(); has_time_spec = false; - is_fragment = false; + more_fragments = false; + fragment_offset = 0; } tx_metadata_t::tx_metadata_t(void){ diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index d70248682..647a8bf1c 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -67,11 +67,7 @@ void usrp2_impl::init_ddc_config(void){ update_ddc_config(); //initial command that kills streaming (in case if was left on) - stream_cmd_t stream_cmd_off; - stream_cmd_off.stream_now = true; - stream_cmd_off.continuous = false; - stream_cmd_off.num_samps = 0; - issue_ddc_stream_cmd(stream_cmd_off); + issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); } void usrp2_impl::update_ddc_config(void){ @@ -90,11 +86,33 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ usrp2_ctrl_data_t out_data; out_data.id = htonl(USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO); out_data.data.stream_cmd.now = (stream_cmd.stream_now)? 1 : 0; - out_data.data.stream_cmd.continuous = (stream_cmd.continuous)? 1 : 0; out_data.data.stream_cmd.secs = htonl(stream_cmd.time_spec.secs); out_data.data.stream_cmd.ticks = htonl(stream_cmd.time_spec.ticks); + + //set these to defaults, then change in the switch statement + out_data.data.stream_cmd.continuous = 0; + out_data.data.stream_cmd.chain = 0; out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps); + //setup chain, num samps, and continuous below + switch(stream_cmd.stream_mode){ + case stream_cmd_t::STREAM_MODE_START_CONTINUOUS: + out_data.data.stream_cmd.continuous = 1; + break; + + case stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS: + out_data.data.stream_cmd.num_samps = htonl(0); + break; + + case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE: + //all set by defaults above + break; + + case stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE: + out_data.data.stream_cmd.chain = 1; + break; + } + //send and recv usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data); ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index c168614ee..7f35c8abd 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -129,7 +129,8 @@ typedef struct{ struct { _SINS_ uint8_t now; //stream now? _SINS_ uint8_t continuous; //auto-reload commmands? - _SINS_ uint8_t _pad[2]; + _SINS_ uint8_t chain; + _SINS_ uint8_t _pad[1]; _SINS_ uint32_t secs; _SINS_ uint32_t ticks; _SINS_ uint32_t num_samps; diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c87884ebb..5820841d7 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -222,12 +222,12 @@ size_t usrp2_impl::recv( ){ //perform a receive if no rx data is waiting to be copied if (asio::buffer_size(_rx_copy_buff) == 0){ + _fragment_offset_in_samps = 0; recv_raw(metadata); } //otherwise flag the metadata to show that is is a fragment else{ metadata = rx_metadata_t(); - metadata.is_fragment = true; } //extract the number of samples available to copy @@ -240,6 +240,11 @@ size_t usrp2_impl::recv( ); const boost::uint32_t *items = asio::buffer_cast<const boost::uint32_t*>(_rx_copy_buff); + //setup the fragment flags and offset + metadata.more_fragments = asio::buffer_size(buff)/io_type.size < num_samps; + metadata.fragment_offset = _fragment_offset_in_samps; + _fragment_offset_in_samps += num_samps; //set for next time + //copy the samples from the recv buffer switch(io_type.tid){ case io_type_t::COMPLEX_FLOAT32: diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 55be420cd..7c55d4c3c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -135,6 +135,7 @@ private: ; uhd::transport::smart_buffer::sptr _rx_smart_buff; boost::asio::const_buffer _rx_copy_buff; + size_t _fragment_offset_in_samps; void io_init(void); //udp transports for control and data |