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 | 
