From 5a4545d3f9689dcddd88f9316ad7bd9c489a3925 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 20 Jul 2010 10:58:22 -0700 Subject: uhd: bring timeout parameter to the device::recv call, implement in usrp2 --- host/lib/usrp/usrp2/usrp2_impl.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_impl.hpp') diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index ab23830c0..cae1b21d6 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -224,8 +224,7 @@ public: } size_t send( const std::vector &, size_t, - const uhd::tx_metadata_t &, - const uhd::io_type_t &, + const uhd::tx_metadata_t &, const uhd::io_type_t &, uhd::device::send_mode_t ); size_t get_max_recv_samps_per_packet(void) const{ @@ -233,9 +232,8 @@ public: } size_t recv( const std::vector &, size_t, - uhd::rx_metadata_t &, - const uhd::io_type_t &, - uhd::device::recv_mode_t + uhd::rx_metadata_t &, const uhd::io_type_t &, + uhd::device::recv_mode_t, size_t ); private: -- cgit v1.2.3 From 90465e6bcda596b28ab823e698b078708828da0c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 20 Jul 2010 18:51:36 -0700 Subject: uhd: added async recv message call to device api implemented in usrp2 io impl added async metadata type --- host/examples/benchmark_rx_rate.cpp | 2 +- host/include/uhd/device.hpp | 11 ++++++++ host/include/uhd/types/metadata.hpp | 44 +++++++++++++++++++++++-------- host/lib/transport/vrt_packet_handler.hpp | 18 ++++++------- host/lib/types.cpp | 12 --------- host/lib/usrp/usrp2/io_impl.cpp | 40 ++++++++++++++++++++++++---- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + 7 files changed, 90 insertions(+), 38 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_impl.hpp') diff --git a/host/examples/benchmark_rx_rate.cpp b/host/examples/benchmark_rx_rate.cpp index 752facb0d..8fae813cf 100644 --- a/host/examples/benchmark_rx_rate.cpp +++ b/host/examples/benchmark_rx_rate.cpp @@ -66,7 +66,7 @@ static inline void test_device( //handle the error codes switch(md.error_code){ case uhd::rx_metadata_t::ERROR_CODE_NONE: - case uhd::rx_metadata_t::ERROR_CODE_OVERRUN: + case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW: break; default: diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ee297ec8a..78bb83c66 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -219,6 +219,17 @@ public: */ virtual size_t get_max_recv_samps_per_packet(void) const = 0; + /*! + * Receive and asynchronous message from the device. + * \param async_metadata the metadata to be filled in + * \param timeout_ms the timeout in milliseconds to wait for a message + * \return true when the async_metadata is valid, false for timeout + */ + virtual bool recv_async_msg( + async_metadata_t &async_metadata, + size_t timeout_ms = default_recv_timeout_ms + ) = 0; + }; } //namespace uhd diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp index 039196250..43ddf875f 100644 --- a/host/include/uhd/types/metadata.hpp +++ b/host/include/uhd/types/metadata.hpp @@ -26,7 +26,7 @@ namespace uhd{ /*! * RX metadata structure for describing sent IF data. - * Includes stream ID, time specification, and fragmentation flags. + * Includes time specification, fragmentation flags, burst flags, and error codes. * The receive routines will convert IF data headers into metadata. */ struct UHD_API rx_metadata_t{ @@ -62,7 +62,7 @@ namespace uhd{ * - timeout: no packet received, underlying code timed-out * - late command: a stream command was issued in the past * - broken chain: expected another stream command - * - overrun: an internal receive buffer has overrun + * - overflow: an internal receive buffer has filled * - bad packet: the buffer was unrecognizable as a vrt packet * * Note: When an overrun occurs in continuous streaming mode, @@ -74,27 +74,21 @@ namespace uhd{ * - none * - late command * - broken chain - * - overrun + * - overflow */ enum error_code_t { ERROR_CODE_NONE = 0x0, ERROR_CODE_TIMEOUT = 0x1, ERROR_CODE_LATE_COMMAND = 0x2, ERROR_CODE_BROKEN_CHAIN = 0x4, - ERROR_CODE_OVERRUN = 0x8, + ERROR_CODE_OVERFLOW = 0x8, ERROR_CODE_BAD_PACKET = 0xf } error_code; - - /*! - * The default constructor: - * Sets the fields to default values (flags set to false). - */ - rx_metadata_t(void); }; /*! * TX metadata structure for describing received IF data. - * Includes stream ID, time specification, and burst flags. + * Includes time specification, and start and stop burst flags. * The send routines will convert the metadata to IF data headers. */ struct UHD_API tx_metadata_t{ @@ -121,6 +115,34 @@ namespace uhd{ tx_metadata_t(void); }; + /*! + * Async metadata structure for describing transmit related events. + */ + struct UHD_API async_metadata_t{ + //! The channel number in a mimo configuration + size_t channel; + + /*! + * Time specification: when the async event occurred. + */ + bool has_time_spec; + time_spec_t time_spec; + + /*! + * Event codes: + * - success: a packet was successfully transmitted + * - underflow: an internal send buffer has emptied + * - sequence error: packet loss between host and device + * - time error: packet had time that was late (or too early) + */ + enum event_code_t { + EVENT_CODE_SUCCESS = 0x1, + EVENT_CODE_UNDERFLOW = 0x2, + EVENT_CODE_SEQ_ERROR = 0x4, + EVENT_CODE_TIME_ERROR = 0x8 + } event_code; + }; + } //namespace uhd #endif /* INCLUDED_UHD_TYPES_METADATA_HPP */ diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index 07ad9115c..3eddcec6d 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -40,10 +40,10 @@ namespace vrt_packet_handler{ **********************************************************************/ typedef std::vector managed_recv_buffs_t; typedef boost::function get_recv_buffs_t; - typedef boost::function handle_overrun_t; + typedef boost::function handle_overflow_t; typedef boost::function vrt_unpacker_t; - static inline void handle_overrun_nop(size_t){} + static inline void handle_overflow_nop(size_t){} struct recv_state{ //width of the receiver in channels @@ -75,7 +75,7 @@ namespace vrt_packet_handler{ uhd::rx_metadata_t &metadata, double tick_rate, const vrt_unpacker_t &vrt_unpacker, - const handle_overrun_t &handle_overrun, + const handle_overflow_t &handle_overflow, size_t vrt_header_offset_words32 ){ //vrt unpack each managed buffer @@ -99,7 +99,7 @@ namespace vrt_packet_handler{ //extract the context word (we dont know the endianness so mirror the bytes) boost::uint32_t word0 = vrt_data[0] | uhd::byteswap(vrt_data[0]); - if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERRUN) handle_overrun(i); + if (word0 & uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) handle_overflow(i); metadata.error_code = uhd::rx_metadata_t::error_code_t(word0 & 0xf); //break to exit loop and store metadata below @@ -142,7 +142,7 @@ namespace vrt_packet_handler{ double tick_rate, const vrt_unpacker_t &vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, - const handle_overrun_t &handle_overrun, + const handle_overflow_t &handle_overflow, size_t vrt_header_offset_words32 ){ metadata.error_code = uhd::rx_metadata_t::ERROR_CODE_NONE; @@ -157,7 +157,7 @@ namespace vrt_packet_handler{ try{ _recv1_helper( state, metadata, tick_rate, - vrt_unpacker, handle_overrun, + vrt_unpacker, handle_overflow, vrt_header_offset_words32 ); }catch(const std::exception &e){ @@ -216,7 +216,7 @@ namespace vrt_packet_handler{ double tick_rate, const vrt_unpacker_t &vrt_unpacker, const get_recv_buffs_t &get_recv_buffs, - const handle_overrun_t &handle_overrun = &handle_overrun_nop, + const handle_overflow_t &handle_overflow = &handle_overflow_nop, size_t vrt_header_offset_words32 = 0 ){ switch(recv_mode){ @@ -233,7 +233,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, - handle_overrun, + handle_overflow, vrt_header_offset_words32 ); } @@ -253,7 +253,7 @@ namespace vrt_packet_handler{ tick_rate, vrt_unpacker, get_recv_buffs, - handle_overrun, + handle_overflow, vrt_header_offset_words32 ); if (num_samps == 0) break; //had a recv timeout or error, break loop diff --git a/host/lib/types.cpp b/host/lib/types.cpp index fdc435fef..1cfe84832 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -98,18 +98,6 @@ stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode): /*********************************************************************** * metadata **********************************************************************/ -rx_metadata_t::rx_metadata_t(void): - has_time_spec(false), - time_spec(time_spec_t()), - more_fragments(false), - fragment_offset(0), - start_of_burst(false), - end_of_burst(false), - error_code(ERROR_CODE_NONE) -{ - /* NOP */ -} - tx_metadata_t::tx_metadata_t(void): has_time_spec(false), time_spec(time_spec_t()), diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 1947fdf00..455a30b47 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -44,7 +44,8 @@ struct usrp2_impl::io_impl{ io_impl(size_t num_frames, size_t width): packet_handler_recv_state(width), - recv_pirate_booty(alignment_buffer_type::make(num_frames, width)) + recv_pirate_booty(alignment_buffer_type::make(num_frames, width)), + async_msg_fifo(bounded_buffer::make(100/*messages deep*/)) { /* NOP */ } @@ -69,6 +70,7 @@ struct usrp2_impl::io_impl{ boost::thread_group recv_pirate_crew; bool recv_pirate_crew_raiding; alignment_buffer_type::sptr recv_pirate_booty; + bounded_buffer::sptr async_msg_fifo; size_t recv_timeout_ms; }; @@ -94,18 +96,34 @@ void usrp2_impl::io_impl::recv_pirate_loop( //extract the vrt header packet info vrt::if_packet_info_t if_packet_info; if_packet_info.num_packet_words32 = buff->size()/sizeof(boost::uint32_t); - vrt::if_hdr_unpack_be(buff->cast(), if_packet_info); + const boost::uint32_t *vrt_hdr = buff->cast(); + vrt::if_hdr_unpack_be(vrt_hdr, if_packet_info); - //handle a tx async report message (TODO forward info) + //handle a tx async report message if (if_packet_info.sid == 1 and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ - std::cerr << "U"; + const boost::uint32_t *vrt_data = vrt_hdr + if_packet_info.num_header_words32; + //extract the context word (we dont know the endianness so mirror the bytes) + boost::uint32_t word0 = vrt_data[0] | uhd::byteswap(vrt_data[0]); + + //fill in the async metadata + async_metadata_t metadata; + metadata.channel = index; + metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; + metadata.time_spec = time_spec_t( + time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), mboard->get_master_clock_freq() + ); + metadata.event_code = uhd::async_metadata_t::event_code_t(word0 & 0xf); + + //print the famous U, and push the metadata into the message queue + if (metadata.event_code == async_metadata_t::EVENT_CODE_UNDERFLOW) std::cerr << "U"; + async_msg_fifo->push_with_pop_on_full(metadata); continue; } //handle the packet count / sequence number if (if_packet_info.packet_count != next_packet_seq){ //std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16; - std::cerr << "O"; //report overrun (drops in the kernel) + std::cerr << "O"; //report overflow (drops in the kernel) } next_packet_seq = (if_packet_info.packet_count+1)%16; @@ -156,6 +174,18 @@ void usrp2_impl::io_init(void){ std::cout << "Recv pirate num frames: " << num_frames << std::endl; } +/*********************************************************************** + * Async Data + **********************************************************************/ +bool usrp2_impl::recv_async_msg( + async_metadata_t &async_metadata, size_t timeout_ms +){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + return _io_impl->async_msg_fifo->pop_with_timed_wait( + async_metadata, boost::posix_time::milliseconds(timeout_ms) + ); +} + /*********************************************************************** * Send Data **********************************************************************/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index cae1b21d6..2eaf12350 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -235,6 +235,7 @@ public: uhd::rx_metadata_t &, const uhd::io_type_t &, uhd::device::recv_mode_t, size_t ); + bool recv_async_msg(uhd::async_metadata_t &, size_t); private: //device properties interface -- cgit v1.2.3 From c2b97490b7920f67d7522a1640b9c53b014a5349 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 23 Jul 2010 22:55:30 -0700 Subject: usrp2: added codec impl for codec properties to usrp2 --- host/lib/usrp/usrp2/CMakeLists.txt | 1 + host/lib/usrp/usrp2/codec_impl.cpp | 96 +++++++++++++++++++++++++++++++++++++ host/lib/usrp/usrp2/dboard_impl.cpp | 8 ++++ host/lib/usrp/usrp2/mboard_impl.cpp | 3 ++ host/lib/usrp/usrp2/usrp2_impl.hpp | 9 ++++ host/utils/uhd_usrp_probe.cpp | 15 ++++++ 6 files changed, 132 insertions(+) create mode 100644 host/lib/usrp/usrp2/codec_impl.cpp (limited to 'host/lib/usrp/usrp2/usrp2_impl.hpp') diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt index 99d0b8bdd..796126d07 100644 --- a/host/lib/usrp/usrp2/CMakeLists.txt +++ b/host/lib/usrp/usrp2/CMakeLists.txt @@ -22,6 +22,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp + ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp diff --git a/host/lib/usrp/usrp2/codec_impl.cpp b/host/lib/usrp/usrp2/codec_impl.cpp new file mode 100644 index 000000000..b9d51abf5 --- /dev/null +++ b/host/lib/usrp/usrp2/codec_impl.cpp @@ -0,0 +1,96 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "usrp2_impl.hpp" +#include +#include + +using namespace uhd; +using namespace uhd::usrp; + +/*********************************************************************** + * Helper Methods + **********************************************************************/ +void usrp2_mboard_impl::codec_init(void){ + //make proxies + _rx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp2_mboard_impl::rx_codec_get, this, _1, _2), + boost::bind(&usrp2_mboard_impl::rx_codec_set, this, _1, _2) + ); + _tx_codec_proxy = wax_obj_proxy::make( + boost::bind(&usrp2_mboard_impl::tx_codec_get, this, _1, _2), + boost::bind(&usrp2_mboard_impl::tx_codec_set, this, _1, _2) + ); +} + +/*********************************************************************** + * RX Codec Properties + **********************************************************************/ +void usrp2_mboard_impl::rx_codec_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp2 adc"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(); //no gain elements to be controlled + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp2_mboard_impl::rx_codec_set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} + +/*********************************************************************** + * TX Codec Properties + **********************************************************************/ +void usrp2_mboard_impl::tx_codec_get(const wax::obj &key_, wax::obj &val){ + wax::obj key; std::string name; + boost::tie(key, name) = extract_named_prop(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case CODEC_PROP_NAME: + val = std::string("usrp2 dac - ad9777"); + return; + + case CODEC_PROP_OTHERS: + val = prop_names_t(); + return; + + case CODEC_PROP_GAIN_NAMES: + val = prop_names_t(); //no gain elements to be controlled + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void usrp2_mboard_impl::tx_codec_set(const wax::obj &, const wax::obj &){ + UHD_THROW_PROP_SET_ERROR(); +} diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 8942f9d31..de091fcdc 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -92,6 +92,10 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_iface; return; + case DBOARD_PROP_CODEC: + val = _rx_codec_proxy; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -151,6 +155,10 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_iface; return; + case DBOARD_PROP_CODEC: + val = _tx_codec_proxy; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index b3b03c11c..7ec1b9cbd 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -95,6 +95,9 @@ usrp2_mboard_impl::usrp2_mboard_impl( //initialize the clock configuration init_clock_config(); + //init the codec before the dboard + codec_init(); + //init the tx and rx dboards (do last) dboard_init(); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2eaf12350..6d705f14e 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -161,6 +161,15 @@ private: void update_clock_config(void); void set_time_spec(const uhd::time_spec_t &time_spec, bool now); + //properties interface for the codec + void codec_init(void); + void rx_codec_get(const wax::obj &, wax::obj &); + void rx_codec_set(const wax::obj &, const wax::obj &); + void tx_codec_get(const wax::obj &, wax::obj &); + void tx_codec_set(const wax::obj &, const wax::obj &); + wax_obj_proxy::sptr _rx_codec_proxy; + wax_obj_proxy::sptr _tx_codec_proxy; + //properties interface for rx dboard void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp index 1b73b5788..9587ea9a3 100644 --- a/host/utils/uhd_usrp_probe.cpp +++ b/host/utils/uhd_usrp_probe.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +95,19 @@ static std::string get_subdev_pp_string(const std::string &type, wax::obj subdev return ss.str(); } +static std::string get_codec_pp_string(const std::string &type, wax::obj codec){ + std::stringstream ss; + ss << boost::format("%s Codec: %s") % type % codec[usrp::CODEC_PROP_NAME].as() << std::endl; + //ss << std::endl; + prop_names_t gain_names(codec[usrp::CODEC_PROP_GAIN_NAMES].as()); + if (gain_names.size() == 0) ss << "Gain Elements: None" << std::endl; + BOOST_FOREACH(const std::string &gain_name, gain_names){ + gain_range_t gain_range(codec[named_prop_t(usrp::CODEC_PROP_GAIN_RANGE, gain_name)].as()); + ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.min % gain_range.max % gain_range.step << std::endl; + } + return ss.str(); +} + static std::string get_dboard_pp_string(const std::string &type, wax::obj dboard){ std::stringstream ss; ss << boost::format("%s Dboard: %s") % type % dboard[usrp::DBOARD_PROP_NAME].as() << std::endl; @@ -101,6 +115,7 @@ static std::string get_dboard_pp_string(const std::string &type, wax::obj dboard BOOST_FOREACH(const std::string &subdev_name, dboard[usrp::DBOARD_PROP_SUBDEV_NAMES].as()){ ss << make_border(get_subdev_pp_string(type, dboard[named_prop_t(usrp::DBOARD_PROP_SUBDEV, subdev_name)])); } + ss << make_border(get_codec_pp_string(type, dboard[usrp::DBOARD_PROP_CODEC])); return ss.str(); } -- cgit v1.2.3 From a333a01ac0d1d0cb011d52f04bed2534a708f944 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 5 Aug 2010 16:27:16 -0700 Subject: uhd: implemented subdev spec in mimo and simple usrp wrappers. implemented subdev spec in usrp2 mboard impl removed subdevs used in dboard impl --- host/include/uhd/usrp/dboard_props.hpp | 1 - host/include/uhd/usrp/mboard_props.hpp | 2 + host/include/uhd/usrp/mimo_usrp.hpp | 5 + host/include/uhd/usrp/simple_usrp.hpp | 5 + host/lib/usrp/mimo_usrp.cpp | 169 ++++++++++++++++++--------------- host/lib/usrp/simple_usrp.cpp | 131 +++++++++++++------------ host/lib/usrp/usrp2/dboard_impl.cpp | 32 ------- host/lib/usrp/usrp2/mboard_impl.cpp | 46 +++++++++ host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 9 files changed, 223 insertions(+), 172 deletions(-) (limited to 'host/lib/usrp/usrp2/usrp2_impl.hpp') diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp index 4d5c5efbd..8a6ef9129 100644 --- a/host/include/uhd/usrp/dboard_props.hpp +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -29,7 +29,6 @@ namespace uhd{ namespace usrp{ DBOARD_PROP_NAME = 'n', //ro, std::string DBOARD_PROP_SUBDEV = 's', //ro, wax::obj DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t - DBOARD_PROP_USED_SUBDEVS = 'u', //ro, prop_names_t DBOARD_PROP_DBOARD_ID = 'i', //rw, dboard_id_t DBOARD_PROP_DBOARD_IFACE = 'f' //ro, dboard_iface::sptr //DBOARD_PROP_CODEC //ro, wax::obj //----> not sure, dont have to deal with yet diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp index a432ce50c..0f250f439 100644 --- a/host/include/uhd/usrp/mboard_props.hpp +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -39,6 +39,8 @@ namespace uhd{ namespace usrp{ MBOARD_PROP_RX_DBOARD_NAMES = 'E', //ro, prop_names_t MBOARD_PROP_TX_DBOARD = 'v', //ro, wax::obj MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t + MBOARD_PROP_RX_SUBDEV_SPEC = 'r', //rw, subdev_spec_t + MBOARD_PROP_TX_SUBDEV_SPEC = 'R', //rw, subdev_spec_t MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t MBOARD_PROP_TIME_NOW = 't', //rw, time_spec_t MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp index fd0f4596f..9856f9d32 100644 --- a/host/include/uhd/usrp/mimo_usrp.hpp +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,8 @@ public: /******************************************************************* * RX methods ******************************************************************/ + virtual void set_rx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; + virtual void set_rx_rate_all(double rate) = 0; virtual double get_rx_rate_all(void) = 0; @@ -148,6 +151,8 @@ public: /******************************************************************* * TX methods ******************************************************************/ + virtual void set_tx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; + virtual void set_tx_rate_all(double rate) = 0; virtual double get_tx_rate_all(void) = 0; diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp index a100579ce..a6275cfcc 100644 --- a/host/include/uhd/usrp/simple_usrp.hpp +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,8 @@ public: /******************************************************************* * RX methods ******************************************************************/ + virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + virtual void set_rx_rate(double rate) = 0; virtual double get_rx_rate(void) = 0; @@ -135,6 +138,8 @@ public: /******************************************************************* * TX methods ******************************************************************/ + virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + virtual void set_tx_rate(double rate) = 0; virtual double get_tx_rate(void) = 0; diff --git a/host/lib/usrp/mimo_usrp.cpp b/host/lib/usrp/mimo_usrp.cpp index ec0f1dcc8..5fb3571ec 100644 --- a/host/lib/usrp/mimo_usrp.cpp +++ b/host/lib/usrp/mimo_usrp.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -46,29 +47,12 @@ public: mimo_usrp_impl(const device_addr_t &addr){ _dev = device::make(addr); - //extract each mboard and its sub-devices - BOOST_FOREACH(const std::string &name, (*_dev)[DEVICE_PROP_MBOARD_NAMES].as()){ - _mboards.push_back((*_dev)[named_prop_t(DEVICE_PROP_MBOARD, name)]); - _rx_dsps.push_back(_mboards.back()[MBOARD_PROP_RX_DSP]); - _tx_dsps.push_back(_mboards.back()[MBOARD_PROP_TX_DSP]); - - //extract rx subdevice - _rx_dboards.push_back(_mboards.back()[MBOARD_PROP_RX_DBOARD]); - std::string rx_subdev_in_use = _rx_dboards.back()[DBOARD_PROP_USED_SUBDEVS].as().at(0); - _rx_subdevs.push_back(_rx_dboards.back()[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]); - - //extract tx subdevice - _tx_dboards.push_back(_mboards.back()[MBOARD_PROP_TX_DBOARD]); - std::string tx_subdev_in_use = _tx_dboards.back()[DBOARD_PROP_USED_SUBDEVS].as().at(0); - _tx_subdevs.push_back(_tx_dboards.back()[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]); - } - //set the clock config across all mboards (TODO set through api) clock_config_t clock_config; clock_config.ref_source = clock_config_t::REF_SMA; clock_config.pps_source = clock_config_t::PPS_SMA; - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; } } @@ -87,7 +71,7 @@ public: ) % (*_dev)[DEVICE_PROP_NAME].as() ); - for (size_t i = 0; i < get_num_channels(); i++){ + for (size_t chan = 0; chan < get_num_channels(); chan++){ buff += str(boost::format( " Channel: %u\n" " Mboard: %s\n" @@ -97,21 +81,21 @@ public: " TX DSP: %s\n" " TX Dboard: %s\n" " TX Subdev: %s\n" - ) % i - % _mboards.at(i)[MBOARD_PROP_NAME].as() - % _rx_dsps.at(i)[DSP_PROP_NAME].as() - % _rx_dboards.at(i)[DBOARD_PROP_NAME].as() - % _rx_subdevs.at(i)[SUBDEV_PROP_NAME].as() - % _tx_dsps.at(i)[DSP_PROP_NAME].as() - % _tx_dboards.at(i)[DBOARD_PROP_NAME].as() - % _tx_subdevs.at(i)[SUBDEV_PROP_NAME].as() + ) % chan + % _mboard(chan)[MBOARD_PROP_NAME].as() + % _rx_dsp(chan)[DSP_PROP_NAME].as() + % _rx_dboard(chan)[DBOARD_PROP_NAME].as() + % _rx_subdev(chan)[SUBDEV_PROP_NAME].as() + % _tx_dsp(chan)[DSP_PROP_NAME].as() + % _tx_dboard(chan)[DBOARD_PROP_NAME].as() + % _tx_subdev(chan)[SUBDEV_PROP_NAME].as() ); } return buff; } size_t get_num_channels(void){ - return _mboards.size(); + return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as().size(); } /******************************************************************* @@ -119,12 +103,12 @@ public: ******************************************************************/ time_spec_t get_time_now(void){ //the time on the first mboard better be the same on all - return _mboards.front()[MBOARD_PROP_TIME_NOW].as(); + return _mboard(0)[MBOARD_PROP_TIME_NOW].as(); } void set_time_next_pps(const time_spec_t &time_spec){ - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; } } @@ -146,33 +130,38 @@ public: boost::this_thread::sleep(boost::posix_time::seconds(1)); //verify that the time registers are read to be within a few RTT - for (size_t i = 1; i < get_num_channels(); i++){ - time_spec_t time_0 = _mboards.front()[MBOARD_PROP_TIME_NOW].as(); - time_spec_t time_i = _mboards.at(i)[MBOARD_PROP_TIME_NOW].as(); + for (size_t chan = 1; chan < get_num_channels(); chan++){ + time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as(); + time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as(); if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big - std::cerr << boost::format( - "Error: time deviation between board %d and board 0.\n" - " Board 0 time is %f seconds.\n" - " Board %d time is %f seconds.\n" - ) % i % time_0.get_real_secs() % i % time_i.get_real_secs() << std::endl; + uhd::print_warning(str(boost::format( + "Detected time deviation between board %d and board 0.\n" + "Board 0 time is %f seconds.\n" + "Board %d time is %f seconds.\n" + ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); } } } void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - BOOST_FOREACH(wax::obj mboard, _mboards){ - mboard[MBOARD_PROP_STREAM_CMD] = stream_cmd; + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; } } /******************************************************************* * RX methods ******************************************************************/ + void set_rx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + } + void set_rx_rate_all(double rate){ std::vector _actual_rates; - BOOST_FOREACH(wax::obj rx_dsp, _rx_dsps){ - rx_dsp[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(rx_dsp[DSP_PROP_HOST_RATE].as()); + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as()); } _rx_rate = _actual_rates.front(); if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( @@ -185,61 +174,66 @@ public: } tune_result_t set_rx_freq(size_t chan, double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), target_freq); } tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan), target_freq, lo_off); + return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), target_freq, lo_off); } double get_rx_freq(size_t chan){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdevs.at(chan), _rx_dsps.at(chan)); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan)); } freq_range_t get_rx_freq_range(size_t chan){ - return add_dsp_shift(_rx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsps.at(chan)); + return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp(chan)); } void set_rx_gain(size_t chan, float gain){ - _rx_subdevs.at(chan)[SUBDEV_PROP_GAIN] = gain; + _rx_subdev(chan)[SUBDEV_PROP_GAIN] = gain; } float get_rx_gain(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_GAIN].as(); + return _rx_subdev(chan)[SUBDEV_PROP_GAIN].as(); } gain_range_t get_rx_gain_range(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_GAIN_RANGE].as(); + return _rx_subdev(chan)[SUBDEV_PROP_GAIN_RANGE].as(); } void set_rx_antenna(size_t chan, const std::string &ant){ - _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA] = ant; + _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; } std::string get_rx_antenna(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA].as(); + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); } std::vector get_rx_antennas(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); } bool get_rx_lo_locked(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_LO_LOCKED].as(); + return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } float read_rssi(size_t chan){ - return _rx_subdevs.at(chan)[SUBDEV_PROP_RSSI].as(); + return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as(); } /******************************************************************* * TX methods ******************************************************************/ + void set_tx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec){ + UHD_ASSERT_THROW(spec.size() <= 1); + _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + } + void set_tx_rate_all(double rate){ std::vector _actual_rates; - BOOST_FOREACH(wax::obj tx_dsp, _tx_dsps){ - tx_dsp[DSP_PROP_HOST_RATE] = rate; - _actual_rates.push_back(tx_dsp[DSP_PROP_HOST_RATE].as()); + for (size_t chan = 0; chan < get_num_channels(); chan++){ + _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; + _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as()); } _tx_rate = _actual_rates.front(); if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( @@ -252,58 +246,77 @@ public: } tune_result_t set_tx_freq(size_t chan, double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), target_freq); } tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan), target_freq, lo_off); + return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), target_freq, lo_off); } double get_tx_freq(size_t chan){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdevs.at(chan), _tx_dsps.at(chan)); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan)); } freq_range_t get_tx_freq_range(size_t chan){ - return add_dsp_shift(_tx_subdevs.at(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsps.at(chan)); + return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp(chan)); } void set_tx_gain(size_t chan, float gain){ - _tx_subdevs.at(chan)[SUBDEV_PROP_GAIN] = gain; + _tx_subdev(chan)[SUBDEV_PROP_GAIN] = gain; } float get_tx_gain(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_GAIN].as(); + return _tx_subdev(chan)[SUBDEV_PROP_GAIN].as(); } gain_range_t get_tx_gain_range(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_GAIN_RANGE].as(); + return _tx_subdev(chan)[SUBDEV_PROP_GAIN_RANGE].as(); } void set_tx_antenna(size_t chan, const std::string &ant){ - _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA] = ant; + _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; } std::string get_tx_antenna(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA].as(); + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as(); } std::vector get_tx_antennas(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as(); } bool get_tx_lo_locked(size_t chan){ - return _tx_subdevs.at(chan)[SUBDEV_PROP_LO_LOCKED].as(); + return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as(); } private: device::sptr _dev; - std::vector _mboards; - std::vector _rx_dsps; - std::vector _tx_dsps; - std::vector _rx_dboards; - std::vector _tx_dboards; - std::vector _rx_subdevs; - std::vector _tx_subdevs; + wax::obj _mboard(size_t chan){ + prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as(); + return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; + } + wax::obj _rx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(size_t chan){ + return _mboard(chan)[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().first; + return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(size_t chan){ + std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().first; + return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().first; + return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(size_t chan){ + std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().first; + return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } //shadows double _rx_rate, _tx_rate; diff --git a/host/lib/usrp/simple_usrp.cpp b/host/lib/usrp/simple_usrp.cpp index 5cb9511f4..1606ad2e8 100644 --- a/host/lib/usrp/simple_usrp.cpp +++ b/host/lib/usrp/simple_usrp.cpp @@ -42,19 +42,6 @@ class simple_usrp_impl : public simple_usrp{ public: simple_usrp_impl(const device_addr_t &addr){ _dev = device::make(addr); - _mboard = (*_dev)[DEVICE_PROP_MBOARD]; - _rx_dsp = _mboard[MBOARD_PROP_RX_DSP]; - _tx_dsp = _mboard[MBOARD_PROP_TX_DSP]; - - //extract rx subdevice - _rx_dboard = _mboard[MBOARD_PROP_RX_DBOARD]; - std::string rx_subdev_in_use = _rx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); - _rx_subdev = _rx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, rx_subdev_in_use)]; - - //extract tx subdevice - _tx_dboard = _mboard[MBOARD_PROP_TX_DBOARD]; - std::string tx_subdev_in_use = _tx_dboard[DBOARD_PROP_USED_SUBDEVS].as().at(0); - _tx_subdev = _tx_dboard[named_prop_t(DBOARD_PROP_SUBDEV, tx_subdev_in_use)]; } ~simple_usrp_impl(void){ @@ -78,13 +65,13 @@ public: " TX Subdev: %s\n" ) % (*_dev)[DEVICE_PROP_NAME].as() - % _mboard[MBOARD_PROP_NAME].as() - % _rx_dsp[DSP_PROP_NAME].as() - % _rx_dboard[DBOARD_PROP_NAME].as() - % _rx_subdev[SUBDEV_PROP_NAME].as() - % _tx_dsp[DSP_PROP_NAME].as() - % _tx_dboard[DBOARD_PROP_NAME].as() - % _tx_subdev[SUBDEV_PROP_NAME].as() + % _mboard()[MBOARD_PROP_NAME].as() + % _rx_dsp()[DSP_PROP_NAME].as() + % _rx_dboard()[DBOARD_PROP_NAME].as() + % _rx_subdev()[SUBDEV_PROP_NAME].as() + % _tx_dsp()[DSP_PROP_NAME].as() + % _tx_dboard()[DBOARD_PROP_NAME].as() + % _tx_subdev()[SUBDEV_PROP_NAME].as() ); } @@ -92,148 +79,174 @@ public: * Misc ******************************************************************/ time_spec_t get_time_now(void){ - return _mboard[MBOARD_PROP_TIME_NOW].as(); + return _mboard()[MBOARD_PROP_TIME_NOW].as(); } void set_time_now(const time_spec_t &time_spec){ - _mboard[MBOARD_PROP_TIME_NOW] = time_spec; + _mboard()[MBOARD_PROP_TIME_NOW] = time_spec; } void set_time_next_pps(const time_spec_t &time_spec){ - _mboard[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; + _mboard()[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; } void issue_stream_cmd(const stream_cmd_t &stream_cmd){ - _mboard[MBOARD_PROP_STREAM_CMD] = stream_cmd; + _mboard()[MBOARD_PROP_STREAM_CMD] = stream_cmd; } void set_clock_config(const clock_config_t &clock_config){ - _mboard[MBOARD_PROP_CLOCK_CONFIG] = clock_config; + _mboard()[MBOARD_PROP_CLOCK_CONFIG] = clock_config; } /******************************************************************* * RX methods ******************************************************************/ + void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; + } + void set_rx_rate(double rate){ - _rx_dsp[DSP_PROP_HOST_RATE] = rate; + _rx_dsp()[DSP_PROP_HOST_RATE] = rate; } double get_rx_rate(void){ - return _rx_dsp[DSP_PROP_HOST_RATE].as(); + return _rx_dsp()[DSP_PROP_HOST_RATE].as(); } tune_result_t set_rx_freq(double target_freq){ - return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq); + return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq); } tune_result_t set_rx_freq(double target_freq, double lo_off){ - return tune_rx_subdev_and_dsp(_rx_subdev, _rx_dsp, target_freq, lo_off); + return tune_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp(), target_freq, lo_off); } double get_rx_freq(void){ - return derive_freq_from_rx_subdev_and_dsp(_rx_subdev, _rx_dsp); + return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(), _rx_dsp()); } freq_range_t get_rx_freq_range(void){ - return add_dsp_shift(_rx_subdev[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp); + return add_dsp_shift(_rx_subdev()[SUBDEV_PROP_FREQ_RANGE].as(), _rx_dsp()); } void set_rx_gain(float gain){ - _rx_subdev[SUBDEV_PROP_GAIN] = gain; + _rx_subdev()[SUBDEV_PROP_GAIN] = gain; } float get_rx_gain(void){ - return _rx_subdev[SUBDEV_PROP_GAIN].as(); + return _rx_subdev()[SUBDEV_PROP_GAIN].as(); } gain_range_t get_rx_gain_range(void){ - return _rx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); + return _rx_subdev()[SUBDEV_PROP_GAIN_RANGE].as(); } void set_rx_antenna(const std::string &ant){ - _rx_subdev[SUBDEV_PROP_ANTENNA] = ant; + _rx_subdev()[SUBDEV_PROP_ANTENNA] = ant; } std::string get_rx_antenna(void){ - return _rx_subdev[SUBDEV_PROP_ANTENNA].as(); + return _rx_subdev()[SUBDEV_PROP_ANTENNA].as(); } std::vector get_rx_antennas(void){ - return _rx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _rx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as(); } bool get_rx_lo_locked(void){ - return _rx_subdev[SUBDEV_PROP_LO_LOCKED].as(); + return _rx_subdev()[SUBDEV_PROP_LO_LOCKED].as(); } float read_rssi(void){ - return _rx_subdev[SUBDEV_PROP_RSSI].as(); + return _rx_subdev()[SUBDEV_PROP_RSSI].as(); } /******************************************************************* * TX methods ******************************************************************/ + void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ + _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; + } + void set_tx_rate(double rate){ - _tx_dsp[DSP_PROP_HOST_RATE] = rate; + _tx_dsp()[DSP_PROP_HOST_RATE] = rate; } double get_tx_rate(void){ - return _tx_dsp[DSP_PROP_HOST_RATE].as(); + return _tx_dsp()[DSP_PROP_HOST_RATE].as(); } tune_result_t set_tx_freq(double target_freq){ - return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq); + return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq); } tune_result_t set_tx_freq(double target_freq, double lo_off){ - return tune_tx_subdev_and_dsp(_tx_subdev, _tx_dsp, target_freq, lo_off); + return tune_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp(), target_freq, lo_off); } double get_tx_freq(void){ - return derive_freq_from_tx_subdev_and_dsp(_tx_subdev, _tx_dsp); + return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(), _tx_dsp()); } freq_range_t get_tx_freq_range(void){ - return add_dsp_shift(_tx_subdev[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp); + return add_dsp_shift(_tx_subdev()[SUBDEV_PROP_FREQ_RANGE].as(), _tx_dsp()); } void set_tx_gain(float gain){ - _tx_subdev[SUBDEV_PROP_GAIN] = gain; + _tx_subdev()[SUBDEV_PROP_GAIN] = gain; } float get_tx_gain(void){ - return _tx_subdev[SUBDEV_PROP_GAIN].as(); + return _tx_subdev()[SUBDEV_PROP_GAIN].as(); } gain_range_t get_tx_gain_range(void){ - return _tx_subdev[SUBDEV_PROP_GAIN_RANGE].as(); + return _tx_subdev()[SUBDEV_PROP_GAIN_RANGE].as(); } void set_tx_antenna(const std::string &ant){ - _tx_subdev[SUBDEV_PROP_ANTENNA] = ant; + _tx_subdev()[SUBDEV_PROP_ANTENNA] = ant; } std::string get_tx_antenna(void){ - return _tx_subdev[SUBDEV_PROP_ANTENNA].as(); + return _tx_subdev()[SUBDEV_PROP_ANTENNA].as(); } std::vector get_tx_antennas(void){ - return _tx_subdev[SUBDEV_PROP_ANTENNA_NAMES].as(); + return _tx_subdev()[SUBDEV_PROP_ANTENNA_NAMES].as(); } bool get_tx_lo_locked(void){ - return _tx_subdev[SUBDEV_PROP_LO_LOCKED].as(); + return _tx_subdev()[SUBDEV_PROP_LO_LOCKED].as(); } private: device::sptr _dev; - wax::obj _mboard; - wax::obj _rx_dsp; - wax::obj _tx_dsp; - wax::obj _rx_dboard; - wax::obj _tx_dboard; - wax::obj _rx_subdev; - wax::obj _tx_subdev; + wax::obj _mboard(void){ + return (*_dev)[DEVICE_PROP_MBOARD]; + } + wax::obj _rx_dsp(void){ + return _mboard()[MBOARD_PROP_RX_DSP]; + } + wax::obj _tx_dsp(void){ + return _mboard()[MBOARD_PROP_TX_DSP]; + } + wax::obj _rx_dboard(void){ + std::string db_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().first; + return _mboard()[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; + } + wax::obj _tx_dboard(void){ + std::string db_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().first; + return _mboard()[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; + } + wax::obj _rx_subdev(void){ + std::string sd_name = _mboard()[MBOARD_PROP_RX_SUBDEV_SPEC].as().front().first; + return _rx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } + wax::obj _tx_subdev(void){ + std::string sd_name = _mboard()[MBOARD_PROP_TX_SUBDEV_SPEC].as().front().first; + return _tx_dboard()[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; + } }; /*********************************************************************** diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index 0aeb0ec1a..8f6182fb5 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -53,10 +53,6 @@ void usrp2_mboard_impl::dboard_init(void){ boost::bind(&usrp2_mboard_impl::tx_dboard_get, this, _1, _2), boost::bind(&usrp2_mboard_impl::tx_dboard_set, this, _1, _2) ); - - //init the subdevs in use (use the first subdevice) - rx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_rx_subdev_names().at(0))); - tx_dboard_set(DBOARD_PROP_USED_SUBDEVS, prop_names_t(1, _dboard_manager->get_tx_subdev_names().at(0))); } /*********************************************************************** @@ -80,10 +76,6 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_rx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _rx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _rx_db_eeprom.id; return; @@ -98,16 +90,6 @@ void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _rx_subdevs_in_use = val.as(); - UHD_ASSERT_THROW(_rx_subdevs_in_use.size() == 1); - wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0)); - std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as() << std::endl; - _iface->poke32(U2_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( - rx_subdev[SUBDEV_PROP_CONNECTION].as() - )); - } - return; case DBOARD_PROP_DBOARD_ID: _rx_db_eeprom.id = val.as(); @@ -139,10 +121,6 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ val = _dboard_manager->get_tx_subdev_names(); return; - case DBOARD_PROP_USED_SUBDEVS: - val = _tx_subdevs_in_use; - return; - case DBOARD_PROP_DBOARD_ID: val = _tx_db_eeprom.id; return; @@ -157,16 +135,6 @@ void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ switch(key.as()){ - case DBOARD_PROP_USED_SUBDEVS:{ - _tx_subdevs_in_use = val.as(); - UHD_ASSERT_THROW(_tx_subdevs_in_use.size() == 1); - wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0)); - std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as() << std::endl; - _iface->poke32(U2_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( - tx_subdev[SUBDEV_PROP_CONNECTION].as() - )); - } - return; case DBOARD_PROP_DBOARD_ID: _tx_db_eeprom.id = val.as(); diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 7694a164d..c35171fec 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -99,6 +99,10 @@ usrp2_mboard_impl::usrp2_mboard_impl( //init the tx and rx dboards (do last) dboard_init(); + //set default subdev specs + (*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t(); + (*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t(); + //Issue a stop streaming command (in case it was left running). //Since this command is issued before the networking is setup, //most if not all junk packets will never make it to the socket. @@ -263,6 +267,14 @@ void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){ } return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + val = _rx_subdev_spec; + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + val = _tx_subdev_spec; + return; + default: UHD_THROW_PROP_GET_ERROR(); } } @@ -307,6 +319,40 @@ void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){ issue_ddc_stream_cmd(val.as()); return; + case MBOARD_PROP_RX_SUBDEV_SPEC: + _rx_subdev_spec = val.as(); + //handle automatic + if (_rx_subdev_spec.empty()) _rx_subdev_spec.push_back( + subdev_spec_t::pair_t("", _dboard_manager->get_rx_subdev_names().front()) + ); + std::cout << "RX " << _rx_subdev_spec.to_pp_string() << std::endl; + //sanity check + UHD_ASSERT_THROW(_rx_subdev_spec.size() == 1); + uhd::assert_has((*this)[MBOARD_PROP_RX_DBOARD_NAMES].as(), _rx_subdev_spec.front().first, "rx dboard names"); + uhd::assert_has(_dboard_manager->get_rx_subdev_names(), _rx_subdev_spec.front().second, "rx subdev names"); + //set the mux + _iface->poke32(U2_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word( + _dboard_manager->get_rx_subdev(_rx_subdev_spec.front().second)[SUBDEV_PROP_CONNECTION].as() + )); + return; + + case MBOARD_PROP_TX_SUBDEV_SPEC: + _tx_subdev_spec = val.as(); + //handle automatic + if (_tx_subdev_spec.empty()) _tx_subdev_spec.push_back( + subdev_spec_t::pair_t("", _dboard_manager->get_tx_subdev_names().front()) + ); + std::cout << "TX " << _tx_subdev_spec.to_pp_string() << std::endl; + //sanity check + UHD_ASSERT_THROW(_tx_subdev_spec.size() == 1); + uhd::assert_has((*this)[MBOARD_PROP_TX_DBOARD_NAMES].as(), _tx_subdev_spec.front().first, "tx dboard names"); + uhd::assert_has(_dboard_manager->get_tx_subdev_names(), _tx_subdev_spec.front().second, "tx subdev names"); + //set the mux + _iface->poke32(U2_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word( + _dboard_manager->get_tx_subdev(_tx_subdev_spec.front().second)[SUBDEV_PROP_CONNECTION].as() + )); + return; + default: UHD_THROW_PROP_SET_ERROR(); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 2eaf12350..e7e560469 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -35,6 +35,7 @@ #include //mtu #include #include +#include /*! * Make a usrp2 dboard interface. @@ -143,6 +144,7 @@ private: //properties for this mboard void get(const wax::obj &, wax::obj &); void set(const wax::obj &, const wax::obj &); + uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //interfaces usrp2_iface::sptr _iface; @@ -165,14 +167,12 @@ private: void rx_dboard_get(const wax::obj &, wax::obj &); void rx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _rx_dboard_proxy; - uhd::prop_names_t _rx_subdevs_in_use; uhd::usrp::dboard_eeprom_t _rx_db_eeprom; //properties interface for tx dboard void tx_dboard_get(const wax::obj &, wax::obj &); void tx_dboard_set(const wax::obj &, const wax::obj &); wax_obj_proxy::sptr _tx_dboard_proxy; - uhd::prop_names_t _tx_subdevs_in_use; uhd::usrp::dboard_eeprom_t _tx_db_eeprom; //methods and shadows for the ddc dsp -- cgit v1.2.3