From af586ae149fe6f7aa12d4d6766e4216f3f00d1c0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 25 Mar 2010 18:36:16 -0700 Subject: 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. --- firmware/microblaze/apps/txrx.c | 174 ++++++++++++++++-------------- firmware/microblaze/lib/memory_map.h | 3 +- host/examples/rx_timed_samples.cpp | 14 ++- host/include/uhd/props.hpp | 2 - host/include/uhd/simple_device.hpp | 4 +- host/include/uhd/time_spec.hpp | 10 +- host/include/uhd/types.hpp | 52 +++++++-- host/lib/simple_device.cpp | 13 +-- host/lib/time_spec.cpp | 5 - host/lib/transport/udp_zero_copy_asio.cpp | 2 +- host/lib/types.cpp | 15 ++- host/lib/usrp/usrp2/dsp_impl.cpp | 42 +++----- host/lib/usrp/usrp2/fw_common.h | 16 +-- host/lib/usrp/usrp2/io_impl.cpp | 8 +- host/lib/usrp/usrp2/mboard_impl.cpp | 77 +++++++------ host/lib/usrp/usrp2/usrp2_impl.hpp | 10 +- 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 @@ -34,18 +34,12 @@ namespace uhd{ boost::uint32_t secs; 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 +#include #include 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(); + 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(); - _ddc_enabled = new_enabled; //shadow - update_ddc_enabled(); - return; - } - else if (key_name == "stream_at"){ - time_spec_t new_stream_at = val.as(); - _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()); 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()){ - case MBOARD_PROP_CLOCK_CONFIG:{ - clock_config_t clock_config = val.as(); - 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(); + 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 #include #include -#include #include #include #include @@ -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 _ref_source_dict; - uhd::dict _pps_source_dict; - uhd::dict _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 _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; -- cgit v1.2.3