summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-03-25 18:36:16 -0700
committerJosh Blum <josh@joshknows.com>2010-03-25 18:36:16 -0700
commitaf586ae149fe6f7aa12d4d6766e4216f3f00d1c0 (patch)
tree4edc587df783b521c0d900d8785ab05296c6efe3
parent7d195aa792037f0b5bce5085fb2db3512b479575 (diff)
downloaduhd-af586ae149fe6f7aa12d4d6766e4216f3f00d1c0.tar.gz
uhd-af586ae149fe6f7aa12d4d6766e4216f3f00d1c0.tar.bz2
uhd-af586ae149fe6f7aa12d4d6766e4216f3f00d1c0.zip
Overhaullllllled the way we do streaming. There is an odd bug where
a zero length command (now, no chain) used to stop the streaming. Now it seems to do the reverse... must investigate. Made all clock configuration into enums. The strings were painful and there cant be that many variations that enums cant cover them. The enums will make more sense to developers than mystery strings.
-rw-r--r--firmware/microblaze/apps/txrx.c174
-rw-r--r--firmware/microblaze/lib/memory_map.h3
-rw-r--r--host/examples/rx_timed_samples.cpp14
-rw-r--r--host/include/uhd/props.hpp2
-rw-r--r--host/include/uhd/simple_device.hpp4
-rw-r--r--host/include/uhd/time_spec.hpp10
-rw-r--r--host/include/uhd/types.hpp52
-rw-r--r--host/lib/simple_device.cpp13
-rw-r--r--host/lib/time_spec.cpp5
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp2
-rw-r--r--host/lib/types.cpp15
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp42
-rw-r--r--host/lib/usrp/usrp2/fw_common.h16
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp8
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp77
-rw-r--r--host/lib/usrp/usrp2/usrp2_impl.hpp10
16 files changed, 233 insertions, 214 deletions
diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c
index 5eec99c4f..a2e3f0430 100644
--- a/firmware/microblaze/apps/txrx.c
+++ b/firmware/microblaze/apps/txrx.c
@@ -54,11 +54,6 @@
#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
-#if (FW_SETS_SEQNO)
-static int fw_seqno; // used when f/w is filling in sequence numbers
-#endif
-
-
/*
* Full duplex Tx and Rx between ethernet and DSP pipelines
*
@@ -127,18 +122,14 @@ dbsm_t dsp_rx_sm; // the state machine
// The mac address of the host we're sending to.
eth_mac_addr_t host_mac_addr;
-#define TIME_NOW ((uint32_t)(~0))
-
-// variables for streaming mode
-
-static bool streaming_p = false;
-static unsigned int streaming_items_per_frame = 0;
-static uint32_t time_secs = TIME_NOW;
-static uint32_t time_ticks = TIME_NOW;
-static int streaming_frame_count = 0;
+//controls continuous streaming...
+static bool auto_reload_command = false;
+static size_t streaming_items_per_frame = 0;
+static int streaming_frame_count = 0;
#define FRAMES_PER_CMD 2
-bool is_streaming(void){ return streaming_p; }
+static void setup_network(void);
+static void setup_vrt(void);
// ----------------------------------------------------------------
// the fast-path setup global variables
@@ -159,6 +150,9 @@ void handle_udp_data_packet(
struct socket_address src, struct socket_address dst,
unsigned char *payload, int payload_len
){
+ //store the 2nd word as the following:
+ streaming_items_per_frame = ((uint32_t *)payload)[1];
+
//its a tiny payload, load the fast-path variables
fp_mac_addr_src = *ethernet_mac_addr();
arp_cache_lookup_mac(&src.addr, &fp_mac_addr_dst);
@@ -176,6 +170,24 @@ void handle_udp_data_packet(
print_ip_addr(&fp_socket_dst.addr); newline();
printf(" destination udp port: %d\n", fp_socket_dst.port);
newline();
+
+ //setup network and vrt
+ setup_network();
+ setup_vrt();
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+
+}
+
+static void inline issue_stream_command(size_t nsamps, bool now, bool chain, uint32_t secs, uint32_t ticks, bool start){
+ //printf("Stream cmd: nsamps %d, now %d, chain %d, secs %u, ticks %u\n", (int)nsamps, now, chain, secs, ticks);
+ sr_rx_ctrl->cmd = MK_RX_CMD(nsamps, now, chain);
+
+ if (start) dbsm_start(&dsp_rx_sm);
+
+ sr_rx_ctrl->time_secs = secs;
+ sr_rx_ctrl->time_ticks = ticks; // enqueue command
}
#define OTW_GPIO_BANK_TO_NUM(bank) \
@@ -443,20 +455,68 @@ void handle_udp_ctrl_packet(
ctrl_data_out.id = USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE;
break;
- case USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO:
- time_secs = ctrl_data_in->data.streaming.secs;
- time_ticks = ctrl_data_in->data.streaming.ticks;
- streaming_items_per_frame = ctrl_data_in->data.streaming.samples;
+ /*******************************************************************
+ * Streaming
+ ******************************************************************/
+ case USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO:{
+
+ //issue two commands and set the auto-reload flag
+ if (ctrl_data_in->data.stream_cmd.continuous){
+ printf("Setting up continuous streaming...\n");
+ auto_reload_command = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+
+ issue_stream_command(
+ streaming_items_per_frame * FRAMES_PER_CMD,
+ (ctrl_data_in->data.stream_cmd.now == 0)? false : true, //now
+ true, //chain
+ ctrl_data_in->data.stream_cmd.secs,
+ ctrl_data_in->data.stream_cmd.ticks,
+ true //start
+ );
+
+ issue_stream_command(
+ streaming_items_per_frame * FRAMES_PER_CMD,
+ true, //now
+ true, //chain
+ 0, 0, //time does not matter
+ false
+ );
- if (ctrl_data_in->data.streaming.enabled == 0){
- stop_rx_cmd();
}
+
+ //issue regular stream commands (split commands if too large)
else{
- start_rx_streaming_cmd();
- }
+ auto_reload_command = false;
+ size_t num_samps = ctrl_data_in->data.stream_cmd.num_samps;
+ if (num_samps == 0) num_samps = 1; //FIXME hack, zero is used when stopping continuous streaming but it somehow makes it inifinite
+
+ bool chain = num_samps > MAX_SAMPLES_PER_CMD;
+ 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.secs,
+ ctrl_data_in->data.stream_cmd.ticks,
+ false
+ );
- ctrl_data_out.id = USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE;
+ //handle rest of the samples that did not fit into one cmd
+ while(chain){
+ num_samps -= MAX_SAMPLES_PER_CMD;
+ chain = num_samps > MAX_SAMPLES_PER_CMD;
+ issue_stream_command(
+ (chain)? streaming_items_per_frame : num_samps, //nsamps
+ true, //now
+ chain, //chain
+ 0, 0, //time does not matter
+ false
+ );
+ }
+ }
+ ctrl_data_out.id = USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE;
break;
+ }
/*******************************************************************
* DUC
@@ -531,7 +591,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)
// In the future, a hardware state machine will do this...
if ( //warning! magic numbers approaching....
(((buff + ((2 + 14 + 20)/sizeof(uint32_t)))[0] & 0xffff) == USRP2_UDP_DATA_PORT) &&
- ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != 0)
+ ((buff + ((2 + 14 + 20 + 8)/sizeof(uint32_t)))[0] != USRP2_INVALID_VRT_HEADER)
) return false;
//test if its an ip recovery packet
@@ -557,7 +617,7 @@ eth_pkt_inspector(dbsm_t *sm, int bufno)
//------------------------------------------------------------------
-static uint16_t get_vrt_packet_words(void){
+static size_t get_vrt_packet_words(void){
return streaming_items_per_frame + \
USRP2_HOST_RX_VRT_HEADER_WORDS32 + \
USRP2_HOST_RX_VRT_TRAILER_WORDS32;
@@ -567,9 +627,7 @@ static bool vrt_has_trailer(void){
return USRP2_HOST_RX_VRT_TRAILER_WORDS32 > 0;
}
-void
-restart_streaming(void)
-{
+static void setup_vrt(void){
// setup RX DSP regs
sr_rx_ctrl->nsamples_per_pkt = streaming_items_per_frame;
sr_rx_ctrl->nchannels = 1;
@@ -582,26 +640,6 @@ restart_streaming(void)
);
sr_rx_ctrl->vrt_stream_id = 0;
sr_rx_ctrl->vrt_trailer = 0;
-
- streaming_p = true;
- streaming_frame_count = FRAMES_PER_CMD;
-
- sr_rx_ctrl->cmd =
- MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
- (time_ticks==TIME_NOW)?1:0, 1); // conditionally set "now" bit, set "chain" bit
-
- // kick off the state machine
- dbsm_start(&dsp_rx_sm);
-
- sr_rx_ctrl->time_secs = time_secs;
- sr_rx_ctrl->time_ticks = time_ticks; // enqueue first of two commands
-
- // make sure this one and the rest have the "now" and "chain" bits set.
- sr_rx_ctrl->cmd =
- MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame, 1, 1);
-
- sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0; // enqueue second command
}
/*
@@ -630,19 +668,15 @@ link_changed_callback(int speed)
printf("\neth link changed: speed = %d\n", speed);
}
-void
-start_rx_streaming_cmd(void)
-{
- /*
- * Construct ethernet header and preload into two buffers
- */
+static void setup_network(void){
+ //setup header and load into two buffers
struct {
uint32_t ctrl_word;
} mem _AL4;
memset(&mem, 0, sizeof(mem));
- printf("samples per frame: %d\n", streaming_items_per_frame);
- printf("words in a vrt packet %d\n", get_vrt_packet_words());
+ printf("items per frame: %d\n", (int)streaming_items_per_frame);
+ printf("words in a vrt packet %d\n", (int)get_vrt_packet_words());
mem.ctrl_word = get_vrt_packet_words()*sizeof(uint32_t) | 1 << 16;
memcpy_wa(buffer_ram(DSP_RX_BUF_0), &mem, sizeof(mem));
@@ -678,26 +712,6 @@ start_rx_streaming_cmd(void)
sr_udp_sm->udp_hdr.dst_port = fp_socket_dst.port;
sr_udp_sm->udp_hdr.length = UDP_SM_INS_UDP_LEN;
sr_udp_sm->udp_hdr.checksum = UDP_SM_LAST_WORD; // zero UDP checksum
-
- if (FW_SETS_SEQNO)
- fw_seqno = 0;
-
- restart_streaming();
-}
-
-void
-stop_rx_cmd(void)
-{
- if (is_streaming()){
- streaming_p = false;
-
- // no samples, "now", not chained
- sr_rx_ctrl->cmd = MK_RX_CMD(0, 1, 0);
-
- sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0; // enqueue command
- }
-
}
#if (FW_SETS_SEQNO)
@@ -713,10 +727,10 @@ bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
// queue up another rx command when required
- if (streaming_p && --streaming_frame_count == 0){
+ if (auto_reload_command && --streaming_frame_count == 0){
streaming_frame_count = FRAMES_PER_CMD;
sr_rx_ctrl->time_secs = 0;
- sr_rx_ctrl->time_ticks = 0;
+ sr_rx_ctrl->time_ticks = 0; //enqueue last command
}
return false; // we didn't handle the packet
@@ -820,7 +834,7 @@ main(void)
// FIXME Figure out how to handle this robustly.
// Any buffers that are emptying should be allowed to drain...
- if (streaming_p){
+ if (auto_reload_command){
// restart_streaming();
// FIXME report error
}
diff --git a/firmware/microblaze/lib/memory_map.h b/firmware/microblaze/lib/memory_map.h
index bb6a1036d..fed1e5259 100644
--- a/firmware/microblaze/lib/memory_map.h
+++ b/firmware/microblaze/lib/memory_map.h
@@ -525,8 +525,9 @@ typedef struct {
volatile uint32_t pad[7]; // Make each structure 16 elements long
} sr_rx_ctrl_t;
+#define MAX_SAMPLES_PER_CMD 0x3fffffff
#define MK_RX_CMD(nsamples, now, chain) \
- ((((now) & 0x1) << 31) | ((chain & 0x1) << 30) | ((nsamples) & 0x3fffffff))
+ ((((now) & 0x1) << 31) | (((chain) & 0x1) << 30) | ((nsamples) & 0x3fffffff))
#define sr_rx_ctrl ((sr_rx_ctrl_t *) _SR_ADDR(SR_RX_CTRL))
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
index 97f75647e..7d58187cd 100644
--- a/host/examples/rx_timed_samples.cpp
+++ b/host/examples/rx_timed_samples.cpp
@@ -65,9 +65,14 @@ int main(int argc, char *argv[]){
//setup streaming
std::cout << std::endl;
- std::cout << boost::format("Begin streaming %u seconds in the future...")
- % seconds_in_future << std::endl;
- sdev->set_streaming_at(uhd::time_spec_t(seconds_in_future));
+ 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;
+ 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
size_t num_acc_samps = 0; //number of accumulated samples
@@ -83,8 +88,7 @@ int main(int argc, char *argv[]){
num_acc_samps += num_rx_samps;
}
- //finished, stop streaming
- sdev->set_streaming(false);
+ //finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
return 0;
diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp
index 41e0eff63..01746f853 100644
--- a/host/include/uhd/props.hpp
+++ b/host/include/uhd/props.hpp
@@ -76,8 +76,6 @@ namespace uhd{
MBOARD_PROP_TX_DBOARD, //ro, wax::obj
MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t
MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t
- MBOARD_PROP_PPS_SOURCE_NAMES, //ro, prop_names_t
- MBOARD_PROP_REF_SOURCE_NAMES, //ro, prop_names_t
MBOARD_PROP_TIME_NOW, //wo, time_spec_t
MBOARD_PROP_TIME_NEXT_PPS //wo, time_spec_t
};
diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp
index 035757936..bbe0258c7 100644
--- a/host/include/uhd/simple_device.hpp
+++ b/host/include/uhd/simple_device.hpp
@@ -51,9 +51,7 @@ public:
/*******************************************************************
* Streaming
******************************************************************/
- virtual void set_streaming_at(const time_spec_t &time_spec) = 0;
- virtual void set_streaming(bool enb) = 0;
- virtual bool get_streaming(void) = 0;
+ virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0;
/*******************************************************************
* RX methods
diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp
index c1e7cf3a1..e863746ba 100644
--- a/host/include/uhd/time_spec.hpp
+++ b/host/include/uhd/time_spec.hpp
@@ -35,17 +35,11 @@ namespace uhd{
boost::uint32_t ticks;
/*!
- * Create a time_spec_t that holds a wildcard time.
- * This will have implementation-specific meaning.
- */
- time_spec_t(void);
-
- /*!
* Create a time_spec_t from seconds and ticks.
- * \param new_secs the new seconds
+ * \param new_secs the new seconds (default = 0)
* \param new_ticks the new ticks (default = 0)
*/
- time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks = 0);
+ time_spec_t(boost::uint32_t new_secs = 0, boost::uint32_t new_ticks = 0);
/*!
* Create a time_spec_t from boost posix time.
diff --git a/host/include/uhd/types.hpp b/host/include/uhd/types.hpp
index 1439f57a1..3ad3dae82 100644
--- a/host/include/uhd/types.hpp
+++ b/host/include/uhd/types.hpp
@@ -19,6 +19,7 @@
#define INCLUDED_UHD_TYPES_HPP
#include <uhd/config.hpp>
+#include <uhd/time_spec.hpp>
#include <string>
namespace uhd{
@@ -66,18 +67,53 @@ namespace uhd{
* Clock configuration settings:
* The source for the 10MHz reference clock.
* The source and polarity for the PPS clock.
- * Possible settings for the reference and pps source
- * are implementation specific motherboard properties.
- * See the MBOARD_PROP_XXX_SOURCE_NAMES properties.
*/
- struct clock_config_t{
- enum polarity_t {POLARITY_NEG, POLARITY_POS};
- std::string ref_source;
- std::string pps_source;
- polarity_t pps_polarity;
+ struct UHD_API clock_config_t{
+ enum ref_source_t {
+ REF_INT, //internal reference
+ REF_SMA, //external sma port
+ REF_MIMO //mimo cable (usrp2 only)
+ } ref_source;
+ enum pps_source_t {
+ PPS_INT, //there is no internal
+ PPS_SMA, //external sma port
+ PPS_MIMO //mimo cable (usrp2 only)
+ } pps_source;
+ enum pps_polarity_t {
+ PPS_NEG, //negative edge
+ PPS_POS //positive edge
+ } pps_polarity;
clock_config_t(void);
};
+ /*!
+ * Command struct for configuration and control of streaming:
+ *
+ * A stream command defines how the device sends samples to the host.
+ * Streaming is controlled by submitting a stream command to the rx dsp.
+ * 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.
+ * 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{
+ bool stream_now;
+ time_spec_t time_spec;
+ bool continuous;
+ size_t num_samps;
+ stream_cmd_t(void);
+ };
+
} //namespace uhd
#endif /* INCLUDED_UHD_TYPES_HPP */
diff --git a/host/lib/simple_device.cpp b/host/lib/simple_device.cpp
index bb7ddfc68..a25cb12e0 100644
--- a/host/lib/simple_device.cpp
+++ b/host/lib/simple_device.cpp
@@ -167,17 +167,8 @@ public:
/*******************************************************************
* Streaming
******************************************************************/
- void set_streaming_at(const time_spec_t &time_spec){
- _rx_ddc[std::string("stream_at")] = time_spec;
- _rx_ddc[std::string("enabled")] = true;
- }
-
- void set_streaming(bool enb){
- _rx_ddc[std::string("enabled")] = enb;
- }
-
- bool get_streaming(void){
- return _rx_ddc[std::string("enabled")].as<bool>();
+ void issue_stream_cmd(const stream_cmd_t &stream_cmd){
+ _rx_ddc[std::string("stream_cmd")] = stream_cmd;
}
/*******************************************************************
diff --git a/host/lib/time_spec.cpp b/host/lib/time_spec.cpp
index 210010394..98bf28077 100644
--- a/host/lib/time_spec.cpp
+++ b/host/lib/time_spec.cpp
@@ -19,11 +19,6 @@
using namespace uhd;
-time_spec_t::time_spec_t(void){
- secs = ~0;
- ticks = ~0;
-}
-
time_spec_t::time_spec_t(boost::uint32_t new_secs, boost::uint32_t new_ticks){
secs = new_secs;
ticks = new_ticks;
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index 219ae8720..9436f2a13 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -115,7 +115,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){
//implement timeout through polling and sleeping
boost::asio::deadline_timer timer(_socket->get_io_service());
- timer.expires_from_now(boost::posix_time::milliseconds(50));
+ timer.expires_from_now(boost::posix_time::milliseconds(100));
while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index f8a9a9b36..273f87a2d 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -51,7 +51,16 @@ tune_result_t::tune_result_t(void){
* clock config
**********************************************************************/
clock_config_t::clock_config_t(void){
- ref_source = ""; //not a valid setting
- pps_source = ""; //not a valid setting
- pps_polarity = POLARITY_NEG;
+ ref_source = REF_INT,
+ pps_source = PPS_INT,
+ pps_polarity = PPS_NEG;
+}
+
+/***********************************************************************
+ * stream command
+ **********************************************************************/
+stream_cmd_t::stream_cmd_t(void){
+ stream_now = true;
+ continuous = false;
+ num_samps = 0;
}
diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp
index 34cce0afb..44f654863 100644
--- a/host/lib/usrp/usrp2/dsp_impl.cpp
+++ b/host/lib/usrp/usrp2/dsp_impl.cpp
@@ -63,9 +63,8 @@ void usrp2_impl::init_ddc_config(void){
_ddc_freq = 0;
update_ddc_config();
- _ddc_stream_at = time_spec_t();
- _ddc_enabled = false;
- update_ddc_enabled();
+ //initial command that kills streaming (in case if was left on)
+ //issue_ddc_stream_cmd(TODO)
}
void usrp2_impl::update_ddc_config(void){
@@ -86,21 +85,19 @@ void usrp2_impl::update_ddc_config(void){
ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE);
}
-void usrp2_impl::update_ddc_enabled(void){
+void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
//setup the out data
usrp2_ctrl_data_t out_data;
- out_data.id = htonl(USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO);
- out_data.data.streaming.enabled = (_ddc_enabled)? 1 : 0;
- out_data.data.streaming.secs = htonl(_ddc_stream_at.secs);
- out_data.data.streaming.ticks = htonl(_ddc_stream_at.ticks);
- out_data.data.streaming.samples = htonl(_max_rx_samples_per_packet);
+ 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);
+ out_data.data.stream_cmd.num_samps = htonl(stream_cmd.num_samps);
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
- ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE);
-
- //clear the stream at time spec (it must be set for the next round of enable/disable)
- _ddc_stream_at = time_spec_t();
+ ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
}
/***********************************************************************
@@ -120,8 +117,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
("decim")
("decims")
("freq")
- ("enabled")
- ("stream_at")
+ ("stream_cmd")
;
val = others;
}
@@ -147,10 +143,6 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){
val = _ddc_freq;
return;
}
- else if (key_name == "enabled"){
- val = _ddc_enabled;
- return;
- }
throw std::invalid_argument(str(
boost::format("error getting: unknown key with name %s") % key_name
@@ -178,16 +170,8 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){
update_ddc_config();
return;
}
- else if (key_name == "enabled"){
- bool new_enabled = val.as<bool>();
- _ddc_enabled = new_enabled; //shadow
- update_ddc_enabled();
- return;
- }
- else if (key_name == "stream_at"){
- time_spec_t new_stream_at = val.as<time_spec_t>();
- _ddc_stream_at = new_stream_at; //shadow
- //update_ddc_enabled(); //dont update from here
+ else if (key_name == "stream_cmd"){
+ issue_ddc_stream_cmd(val.as<stream_cmd_t>());
return;
}
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 7fcae6fb2..30fee6c32 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -32,6 +32,9 @@ extern "C" {
#define _SINS_
#endif
+//used to differentiate control packets over data port
+#define USRP2_INVALID_VRT_HEADER 0
+
// size of the vrt header and trailer to the host
#define USRP2_HOST_RX_VRT_HEADER_WORDS32 5
#define USRP2_HOST_RX_VRT_TRAILER_WORDS32 1 //FIXME fpga sets wrong header size when no trailer present
@@ -90,8 +93,8 @@ typedef enum{
USRP2_CTRL_ID_SETUP_THIS_DDC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DDC_DUDE,
- USRP2_CTRL_ID_CONFIGURE_STREAMING_FOR_ME_BRO,
- USRP2_CTRL_ID_CONFIGURED_THAT_STREAMING_DUDE,
+ USRP2_CTRL_ID_SEND_STREAM_COMMAND_FOR_ME_BRO,
+ USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE,
USRP2_CTRL_ID_SETUP_THIS_DUC_FOR_ME_BRO,
USRP2_CTRL_ID_TOTALLY_SETUP_THE_DUC_DUDE,
@@ -186,12 +189,13 @@ typedef struct{
_SINS_ uint32_t scale_iq;
} ddc_args;
struct {
- _SINS_ uint8_t enabled;
- _SINS_ uint8_t _pad[3];
+ _SINS_ uint8_t now; //stream now?
+ _SINS_ uint8_t continuous; //auto-reload commmands?
+ _SINS_ uint8_t _pad[2];
_SINS_ uint32_t secs;
_SINS_ uint32_t ticks;
- _SINS_ uint32_t samples;
- } streaming;
+ _SINS_ uint32_t num_samps;
+ } stream_cmd;
struct {
_SINS_ uint32_t freq_word;
_SINS_ uint32_t interp;
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index df0736863..280f124d2 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -41,8 +41,12 @@ void usrp2_impl::io_init(void){
_rx_copy_buff = asio::buffer("", 0);
//send a small data packet so the usrp2 knows the udp source port
- boost::uint32_t zero_data = 0;
- _data_transport->send(asio::buffer(&zero_data, sizeof(zero_data)));
+ //and the maximum number of lines (32 bit words) per packet
+ boost::uint32_t data[2] = {
+ htonl(USRP2_INVALID_VRT_HEADER),
+ htonl(_max_rx_samples_per_packet)
+ };
+ _data_transport->send(asio::buffer(&data, sizeof(data)));
}
#define unrolled_loop(__inst, __len){ \
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index cbca8eec7..c56782c4b 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -35,27 +35,10 @@ void usrp2_impl::mboard_init(void){
}
void usrp2_impl::init_clock_config(void){
- //init the ref source clock config
- _ref_source_dict = boost::assign::map_list_of
- ("int", USRP2_REF_SOURCE_INT)
- ("sma", USRP2_REF_SOURCE_SMA)
- ("mimo", USRP2_REF_SOURCE_MIMO)
- ;
- _clock_config.ref_source = "int";
-
- //init the pps source clock config
- _pps_source_dict = boost::assign::map_list_of
- ("sma", USRP2_PPS_SOURCE_SMA)
- ("mimo", USRP2_PPS_SOURCE_MIMO)
- ;
- _clock_config.pps_source = "sma";
-
- //init the pps polarity clock config
- _pps_polarity_dict = boost::assign::map_list_of
- (clock_config_t::POLARITY_POS, USRP2_PPS_POLARITY_POS)
- (clock_config_t::POLARITY_NEG, USRP2_PPS_POLARITY_NEG)
- ;
- _clock_config.pps_polarity = clock_config_t::POLARITY_NEG;
+ //setup the clock configuration settings
+ _clock_config.ref_source = clock_config_t::REF_INT;
+ _clock_config.pps_source = clock_config_t::PPS_SMA;
+ _clock_config.pps_polarity = clock_config_t::PPS_NEG;
//update the clock config (sends a control packet)
update_clock_config();
@@ -65,9 +48,35 @@ void usrp2_impl::update_clock_config(void){
//setup the out data
usrp2_ctrl_data_t out_data;
out_data.id = htonl(USRP2_CTRL_ID_HERES_A_NEW_CLOCK_CONFIG_BRO);
- out_data.data.clock_config.ref_source = _ref_source_dict [_clock_config.ref_source];
- out_data.data.clock_config.pps_source = _pps_source_dict [_clock_config.pps_source];
- out_data.data.clock_config.pps_polarity = _pps_polarity_dict[_clock_config.pps_polarity];
+
+ //translate ref source enums
+ switch(_clock_config.ref_source){
+ case clock_config_t::REF_INT:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_INT; break;
+ case clock_config_t::REF_SMA:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_SMA; break;
+ case clock_config_t::REF_MIMO:
+ out_data.data.clock_config.ref_source = USRP2_REF_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration ref source");
+ }
+
+ //translate pps source enums
+ switch(_clock_config.pps_source){
+ case clock_config_t::PPS_SMA:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_SMA; break;
+ case clock_config_t::PPS_MIMO:
+ out_data.data.clock_config.pps_source = USRP2_PPS_SOURCE_MIMO; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps source");
+ }
+
+ //translate pps polarity enums
+ switch(_clock_config.pps_polarity){
+ case clock_config_t::PPS_POS:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_POS; break;
+ case clock_config_t::PPS_NEG:
+ out_data.data.clock_config.pps_source = USRP2_PPS_POLARITY_NEG; break;
+ default: throw std::runtime_error("usrp2: unhandled clock configuration pps polarity");
+ }
//send and recv
usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
@@ -184,14 +193,6 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){
val = _clock_config;
return;
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- val = prop_names_t(_pps_source_dict.get_keys());
- return;
-
- case MBOARD_PROP_REF_SOURCE_NAMES:
- val = prop_names_t(_ref_source_dict.get_keys());
- return;
-
case MBOARD_PROP_TIME_NOW:
case MBOARD_PROP_TIME_NEXT_PPS:
throw std::runtime_error("Error: trying to get write-only property on usrp2 mboard");
@@ -234,13 +235,9 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<mboard_prop_t>()){
- case MBOARD_PROP_CLOCK_CONFIG:{
- clock_config_t clock_config = val.as<clock_config_t>();
- assert_has(_pps_source_dict.get_keys(), clock_config.pps_source, "usrp2 pps source");
- assert_has(_ref_source_dict.get_keys(), clock_config.ref_source, "usrp2 ref source");
- _clock_config = clock_config; //shadow
- update_clock_config();
- }
+ case MBOARD_PROP_CLOCK_CONFIG:
+ _clock_config = val.as<clock_config_t>();
+ update_clock_config();
return;
case MBOARD_PROP_TIME_NOW:{
@@ -264,8 +261,6 @@ void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){
case MBOARD_PROP_RX_DBOARD_NAMES:
case MBOARD_PROP_TX_DBOARD:
case MBOARD_PROP_TX_DBOARD_NAMES:
- case MBOARD_PROP_PPS_SOURCE_NAMES:
- case MBOARD_PROP_REF_SOURCE_NAMES:
throw std::runtime_error("Error: trying to set read-only property on usrp2 mboard");
}
diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp
index 55ac0b192..2794cc666 100644
--- a/host/lib/usrp/usrp2/usrp2_impl.hpp
+++ b/host/lib/usrp/usrp2/usrp2_impl.hpp
@@ -21,7 +21,6 @@
#include <uhd/usrp/usrp2.hpp>
#include <uhd/dict.hpp>
#include <uhd/types.hpp>
-#include <uhd/time_spec.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
@@ -146,11 +145,6 @@ private:
void update_clock_config(void);
void set_time_spec(const uhd::time_spec_t &time_spec, bool now);
- //mappings from clock config strings to over the wire enums
- uhd::dict<std::string, usrp2_ref_source_t> _ref_source_dict;
- uhd::dict<std::string, usrp2_pps_source_t> _pps_source_dict;
- uhd::dict<uhd::clock_config_t::polarity_t, usrp2_pps_polarity_t> _pps_polarity_dict;
-
//rx and tx dboard methods and objects
uhd::usrp::dboard_manager::sptr _dboard_manager;
void dboard_init(void);
@@ -178,11 +172,9 @@ private:
std::vector<size_t> _allowed_decim_and_interp_rates;
size_t _ddc_decim;
uhd::freq_t _ddc_freq;
- bool _ddc_enabled;
- uhd::time_spec_t _ddc_stream_at;
void init_ddc_config(void);
void update_ddc_config(void);
- void update_ddc_enabled(void);
+ void issue_ddc_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
//methods and shadows for the duc dsp
size_t _duc_interp;