summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-04-03 19:43:20 -0700
committerJosh Blum <josh@joshknows.com>2010-04-03 19:43:20 -0700
commit83bd55d63972804e62f3890a4a90c8288fcbad0c (patch)
treeb5bf6a8877b37b238f9f540b0b77d1425ed619b9
parentf4ccb204473884126bcff6551d224e263dd5102a (diff)
downloaduhd-83bd55d63972804e62f3890a4a90c8288fcbad0c.tar.gz
uhd-83bd55d63972804e62f3890a4a90c8288fcbad0c.tar.bz2
uhd-83bd55d63972804e62f3890a4a90c8288fcbad0c.zip
extended stream cmd with mode enum, and extended fragment flags in metadata
-rw-r--r--firmware/microblaze/apps/txrx.c4
-rw-r--r--host/examples/rx_timed_samples.cpp5
-rw-r--r--host/include/uhd/device.hpp1
-rw-r--r--host/include/uhd/types/metadata.hpp60
-rw-r--r--host/include/uhd/types/stream_cmd.hpp32
-rw-r--r--host/lib/types.cpp7
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp30
-rw-r--r--host/lib/usrp/usrp2/fw_common.h3
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp7
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp1
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