diff options
-rw-r--r-- | firmware/microblaze/apps/txrx.c | 190 | ||||
-rw-r--r-- | firmware/microblaze/lib/memory_map.h | 3 | ||||
-rw-r--r-- | host/examples/rx_timed_samples.cpp | 14 | ||||
-rw-r--r-- | host/include/uhd/props.hpp | 2 | ||||
-rw-r--r-- | host/include/uhd/simple_device.hpp | 4 | ||||
-rw-r--r-- | host/include/uhd/time_spec.hpp | 10 | ||||
-rw-r--r-- | host/include/uhd/types.hpp | 52 | ||||
-rw-r--r-- | host/lib/simple_device.cpp | 13 | ||||
-rw-r--r-- | host/lib/time_spec.cpp | 5 | ||||
-rw-r--r-- | host/lib/transport/udp_zero_copy_asio.cpp | 2 | ||||
-rw-r--r-- | host/lib/types.cpp | 15 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 42 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/fw_common.h | 16 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 53 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 77 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 9 | ||||
-rw-r--r-- | host/utils/CMakeLists.txt | 2 |
17 files changed, 266 insertions, 243 deletions
diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index b82c7702b..a2e3f0430 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -22,6 +22,8 @@ #include "config.h" #endif +#define DEBUG_MODE 0 //0 for normal operation + #include <lwip/ip.h> #include <lwip/udp.h> #include "u2_init.h" @@ -52,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 * @@ -125,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 @@ -157,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); @@ -174,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) \ @@ -275,7 +289,7 @@ void handle_udp_ctrl_packet( * GPIO ******************************************************************/ case USRP2_CTRL_ID_USE_THESE_GPIO_DDR_SETTINGS_BRO: - hal_gpio_set_ddr( + if (!DEBUG_MODE) hal_gpio_set_ddr( OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.gpio_config.bank), ctrl_data_in->data.gpio_config.value, ctrl_data_in->data.gpio_config.mask @@ -284,7 +298,7 @@ void handle_udp_ctrl_packet( break; case USRP2_CTRL_ID_SET_YOUR_GPIO_PIN_OUTS_BRO: - hal_gpio_write( + if (!DEBUG_MODE) hal_gpio_write( OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.gpio_config.bank), ctrl_data_in->data.gpio_config.value, ctrl_data_in->data.gpio_config.mask @@ -302,7 +316,7 @@ void handle_udp_ctrl_packet( case USRP2_CTRL_ID_USE_THESE_ATR_SETTINGS_BRO:{ //setup the atr registers for this bank int bank = OTW_GPIO_BANK_TO_NUM(ctrl_data_in->data.atr_config.bank); - set_atr_regs( + if (!DEBUG_MODE) set_atr_regs( bank, ctrl_data_in->data.atr_config.rx_value, ctrl_data_in->data.atr_config.tx_value @@ -312,7 +326,7 @@ void handle_udp_ctrl_packet( int mask = ctrl_data_in->data.atr_config.mask; for (int i = 0; i < 16; i++){ // set to either GPIO_SEL_SW or GPIO_SEL_ATR - hal_gpio_set_sel(bank, i, (mask & (1 << i)) ? 'a' : 's'); + if (!DEBUG_MODE) hal_gpio_set_sel(bank, i, (mask & (1 << i)) ? 'a' : 's'); } ctrl_data_out.id = USRP2_CTRL_ID_GOT_THE_ATR_SETTINGS_DUDE; } @@ -441,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 @@ -529,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 @@ -555,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; @@ -565,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; @@ -580,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 } /* @@ -628,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)); @@ -676,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) @@ -711,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 @@ -757,9 +773,9 @@ main(void) #endif output_regs->debug_mux_ctrl = 1; -#if 0 - hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111"); - hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111"); +#if DEBUG_MODE + hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000"); + hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000"); hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff); hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff); #endif @@ -818,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 63944b2bf..1fc8ce14a 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -116,7 +116,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 dc8eea243..280f124d2 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -16,7 +16,6 @@ // #include <complex> -#include <algorithm> #include <boost/format.hpp> #include "usrp2_impl.hpp" @@ -42,20 +41,22 @@ 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(__i, __len, __inst) {\ +#define unrolled_loop(__inst, __len){ \ size_t __i = 0; \ - while(__i < (__len & ~0x7)){ \ - __inst; __i++; __inst; __i++; \ - __inst; __i++; __inst; __i++; \ - __inst; __i++; __inst; __i++; \ - __inst; __i++; __inst; __i++; \ + for(; __i < (__len & ~0x3); __i+= 4){ \ + __inst(__i+0); __inst(__i+1); \ + __inst(__i+2); __inst(__i+3); \ } \ - while(__i < __len){ \ - __inst; __i++;\ + for(; __i < __len; __i++){ \ + __inst(__i); \ } \ } @@ -71,11 +72,12 @@ static inline void host_floats_to_usrp2_items( const fc32_t *host_floats, size_t num_samps ){ - unrolled_loop(i, num_samps,{ - boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); - boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); - usrp2_items[i] = htonl((real << 16) | (imag << 0)); - }); + #define host_floats_to_usrp2_items_i(i){ \ + boost::uint16_t real = boost::int16_t(host_floats[i].real()*shorts_per_float); \ + boost::uint16_t imag = boost::int16_t(host_floats[i].imag()*shorts_per_float); \ + usrp2_items[i] = htonl((real << 16) | (imag << 0)); \ + } + unrolled_loop(host_floats_to_usrp2_items_i, num_samps); } static inline void usrp2_items_to_host_floats( @@ -83,12 +85,13 @@ static inline void usrp2_items_to_host_floats( const boost::uint32_t *usrp2_items, size_t num_samps ){ - unrolled_loop(i, num_samps,{ - boost::uint32_t item = ntohl(usrp2_items[i]); - boost::int16_t real = boost::uint16_t(item >> 16); - boost::int16_t imag = boost::uint16_t(item >> 0); - host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); - }); + #define usrp2_items_to_host_floats_i(i){ \ + boost::uint32_t item = ntohl(usrp2_items[i]); \ + boost::int16_t real = boost::uint16_t(item >> 16); \ + boost::int16_t imag = boost::uint16_t(item >> 0); \ + host_floats[i] = fc32_t(float(real*floats_per_short), float(imag*floats_per_short)); \ + } + unrolled_loop(usrp2_items_to_host_floats_i, num_samps); } static inline void host_items_to_usrp2_items( @@ -96,11 +99,12 @@ static inline void host_items_to_usrp2_items( const boost::uint32_t *host_items, size_t num_samps ){ + #define host_items_to_usrp2_items_i(i) usrp2_items[i] = htonl(host_items[i]) if (is_big_endian){ std::memcpy(usrp2_items, host_items, num_samps*sizeof(boost::uint32_t)); } else{ - unrolled_loop(i, num_samps, usrp2_items[i] = htonl(host_items[i])); + unrolled_loop(host_items_to_usrp2_items_i, num_samps); } } @@ -109,11 +113,12 @@ static inline void usrp2_items_to_host_items( const boost::uint32_t *usrp2_items, size_t num_samps ){ + #define usrp2_items_to_host_items_i(i) host_items[i] = ntohl(usrp2_items[i]) if (is_big_endian){ std::memcpy(host_items, usrp2_items, num_samps*sizeof(boost::uint32_t)); } else{ - unrolled_loop(i, num_samps, host_items[i] = ntohl(usrp2_items[i])); + unrolled_loop(usrp2_items_to_host_items_i, num_samps); } } 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 a2f454c61..3a2963c5a 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -147,11 +147,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); @@ -179,11 +174,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; diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 9ac3f3a52..1fb132937 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -23,4 +23,4 @@ ADD_EXECUTABLE(usrp2_burner usrp2_burner.cpp) TARGET_LINK_LIBRARIES(usrp2_burner uhd) INSTALL(TARGETS usrp2_burner RUNTIME DESTINATION ${PKG_DATA_DIR}/utils) -INSTALL(FILES usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils) +INSTALL(PROGRAMS usrp2_recovery.py DESTINATION ${PKG_DATA_DIR}/utils) |