diff options
| -rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 18 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 20 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/io_impl.cpp | 113 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/mboard_impl.cpp | 78 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 102 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.hpp | 175 | 
6 files changed, 282 insertions, 224 deletions
| diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp index fef486771..fa8d1a674 100644 --- a/host/lib/usrp/usrp2/dboard_impl.cpp +++ b/host/lib/usrp/usrp2/dboard_impl.cpp @@ -33,7 +33,7 @@ using namespace uhd::usrp;  /***********************************************************************   * Helper Methods   **********************************************************************/ -void usrp2_impl::dboard_init(void){ +void usrp2_mboard_impl::dboard_init(void){      //read the dboard eeprom to extract the dboard ids      _rx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_RX_DB, 0, dboard_eeprom_t::num_bytes()));      _tx_db_eeprom = dboard_eeprom_t(_iface->read_eeprom(I2C_ADDR_TX_DB, 0, dboard_eeprom_t::num_bytes())); @@ -46,12 +46,12 @@ void usrp2_impl::dboard_init(void){      //load dboards      _rx_dboard_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_impl::rx_dboard_get, this, _1, _2), -        boost::bind(&usrp2_impl::rx_dboard_set, this, _1, _2) +        boost::bind(&usrp2_mboard_impl::rx_dboard_get, this, _1, _2), +        boost::bind(&usrp2_mboard_impl::rx_dboard_set, this, _1, _2)      );      _tx_dboard_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_impl::tx_dboard_get, this, _1, _2), -        boost::bind(&usrp2_impl::tx_dboard_set, this, _1, _2) +        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) @@ -62,7 +62,7 @@ void usrp2_impl::dboard_init(void){  /***********************************************************************   * RX DBoard Properties   **********************************************************************/ -void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){      wax::obj key; std::string name;      boost::tie(key, name) = extract_named_prop(key_); @@ -96,7 +96,7 @@ void usrp2_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val){      }  } -void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){      switch(key.as<dboard_prop_t>()){      case DBOARD_PROP_USED_SUBDEVS:{              _rx_subdevs_in_use = val.as<prop_names_t>(); @@ -122,7 +122,7 @@ void usrp2_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){  /***********************************************************************   * TX DBoard Properties   **********************************************************************/ -void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){      wax::obj key; std::string name;      boost::tie(key, name) = extract_named_prop(key_); @@ -156,7 +156,7 @@ void usrp2_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val){      }  } -void usrp2_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){      switch(key.as<dboard_prop_t>()){      case DBOARD_PROP_USED_SUBDEVS:{              _tx_subdevs_in_use = val.as<prop_names_t>(); diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 367cde2e1..c315a2eec 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -41,11 +41,11 @@ pick_closest_rate(double exact_rate, const std::vector<rate_t> &rates){      return closest_match;  } -void usrp2_impl::init_ddc_config(void){ +void usrp2_mboard_impl::init_ddc_config(void){      //create the ddc in the rx dsp dict      _rx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_impl::ddc_get, this, _1, _2), -        boost::bind(&usrp2_impl::ddc_set, this, _1, _2) +        boost::bind(&usrp2_mboard_impl::ddc_get, this, _1, _2), +        boost::bind(&usrp2_mboard_impl::ddc_set, this, _1, _2)      );      //initial config and update @@ -56,7 +56,7 @@ void usrp2_impl::init_ddc_config(void){  /***********************************************************************   * DDC Properties   **********************************************************************/ -void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::ddc_get(const wax::obj &key, wax::obj &val){      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME:          val = std::string("usrp2 ddc0"); @@ -82,7 +82,7 @@ void usrp2_impl::ddc_get(const wax::obj &key, wax::obj &val){      }  } -void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::ddc_set(const wax::obj &key, const wax::obj &val){      switch(key.as<dsp_prop_t>()){      case DSP_PROP_FREQ_SHIFT:{ @@ -116,11 +116,11 @@ void usrp2_impl::ddc_set(const wax::obj &key, const wax::obj &val){  /***********************************************************************   * DUC Helper Methods   **********************************************************************/ -void usrp2_impl::init_duc_config(void){ +void usrp2_mboard_impl::init_duc_config(void){      //create the duc in the tx dsp dict      _tx_dsp_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_impl::duc_get, this, _1, _2), -        boost::bind(&usrp2_impl::duc_set, this, _1, _2) +        boost::bind(&usrp2_mboard_impl::duc_get, this, _1, _2), +        boost::bind(&usrp2_mboard_impl::duc_set, this, _1, _2)      );      //initial config and update @@ -131,7 +131,7 @@ void usrp2_impl::init_duc_config(void){  /***********************************************************************   * DUC Properties   **********************************************************************/ -void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){ +void usrp2_mboard_impl::duc_get(const wax::obj &key, wax::obj &val){      switch(key.as<dsp_prop_t>()){      case DSP_PROP_NAME:          val = std::string("usrp2 duc0"); @@ -157,7 +157,7 @@ void usrp2_impl::duc_get(const wax::obj &key, wax::obj &val){      }  } -void usrp2_impl::duc_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::duc_set(const wax::obj &key, const wax::obj &val){      switch(key.as<dsp_prop_t>()){      case DSP_PROP_FREQ_SHIFT:{ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index e3a3a3b17..8b1864e2d 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -20,7 +20,7 @@  #include "usrp2_regs.hpp"  #include <uhd/utils/thread_priority.hpp>  #include <uhd/transport/convert_types.hpp> -#include <uhd/transport/bounded_buffer.hpp> +#include <uhd/transport/alignment_buffer.hpp>  #include <boost/format.hpp>  #include <boost/asio.hpp> //htonl and ntohl  #include <boost/bind.hpp> @@ -36,54 +36,58 @@ namespace asio = boost::asio;   * io impl details (internal to this file)   **********************************************************************/  struct usrp2_impl::io_impl{ +    typedef alignment_buffer<managed_recv_buffer::sptr, time_spec_t> alignment_buffer_type; -    io_impl(zero_copy_if::sptr zc_if); +    io_impl(std::vector<udp_zero_copy::sptr> &zc_ifs);      ~io_impl(void); -    managed_recv_buffer::sptr get_recv_buff(void); +    bool get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs);      //state management for the vrt packet handler code      vrt_packet_handler::recv_state packet_handler_recv_state;      vrt_packet_handler::send_state packet_handler_send_state;      //methods and variables for the recv pirate -    void recv_pirate_loop(zero_copy_if::sptr zc_if); -    boost::thread *recv_pirate_thread; bool recv_pirate_running; -    bounded_buffer<managed_recv_buffer::sptr>::sptr recv_pirate_booty; +    void recv_pirate_loop(zero_copy_if::sptr zc_if, size_t index); +    boost::thread_group recv_pirate_crew; +    bool recv_pirate_crew_running; +    alignment_buffer_type::sptr recv_pirate_booty;  }; -usrp2_impl::io_impl::io_impl(zero_copy_if::sptr zc_if): packet_handler_recv_state(1){ +usrp2_impl::io_impl::io_impl(std::vector<udp_zero_copy::sptr> &zc_ifs): +    packet_handler_recv_state(zc_ifs.size()) +{      //create a large enough booty -    size_t num_frames = zc_if->get_num_recv_frames(); +    size_t num_frames = zc_ifs.at(0)->get_num_recv_frames();      std::cout << "Recv pirate num frames: " << num_frames << std::endl; -    recv_pirate_booty = bounded_buffer<managed_recv_buffer::sptr>::make(num_frames); +    recv_pirate_booty = alignment_buffer_type::make(num_frames, zc_ifs.size()); -    //create a new pirate thread (yarr!!) -    recv_pirate_thread = new boost::thread( -        boost::bind(&usrp2_impl::io_impl::recv_pirate_loop, this, zc_if) -    ); +    //create a new pirate thread for each zc if (yarr!!) +    for (size_t i = 0; i < zc_ifs.size(); i++){ +        recv_pirate_crew.create_thread( +            boost::bind(&usrp2_impl::io_impl::recv_pirate_loop, this, zc_ifs.at(i), i) +        ); +    }  }  usrp2_impl::io_impl::~io_impl(void){ -    recv_pirate_running = false; -    recv_pirate_thread->interrupt(); -    recv_pirate_thread->join(); -    delete recv_pirate_thread; +    recv_pirate_crew_running = false; +    recv_pirate_crew.interrupt_all(); +    recv_pirate_crew.join_all();  } -managed_recv_buffer::sptr usrp2_impl::io_impl::get_recv_buff(void){ -    managed_recv_buffer::sptr buff; +bool usrp2_impl::io_impl::get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs){      boost::this_thread::disable_interruption di; //disable because the wait can throw -    recv_pirate_booty->pop_with_timed_wait(buff, boost::posix_time::milliseconds(100)); -    return buff; //a timeout means that we return a null sptr... +    return recv_pirate_booty->pop_elems_with_timed_wait(buffs, boost::posix_time::milliseconds(100));  } -void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if){ +void usrp2_impl::io_impl::recv_pirate_loop(zero_copy_if::sptr zc_if, size_t index){      set_thread_priority_safe(); -    recv_pirate_running = true; -    while(recv_pirate_running){ +    recv_pirate_crew_running = true; +    while(recv_pirate_crew_running){          managed_recv_buffer::sptr buff = zc_if->get_recv_buff(); -        if (buff->size()) recv_pirate_booty->push_with_pop_on_full(buff); +        //TODO unpack vrt, get time spec, round to nearest packet bound, use below: +        if (buff->size()) recv_pirate_booty->push_with_pop_on_full(buff, time_spec_t(/*todoseq*/), index);      }  } @@ -102,54 +106,54 @@ void usrp2_impl::io_init(void){      _tx_otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;      //send a small data packet so the usrp2 knows the udp source port -    managed_send_buffer::sptr send_buff = _data_transport->get_send_buff(); -    boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); -    memcpy(send_buff->cast<void*>(), &data, sizeof(data)); -    send_buff->commit(sizeof(data)); +    for(size_t i = 0; i < _data_transports.size(); i++){ +        managed_send_buffer::sptr send_buff = _data_transports[i]->get_send_buff(); +        boost::uint32_t data = htonl(USRP2_INVALID_VRT_HEADER); +        memcpy(send_buff->cast<void*>(), &data, sizeof(data)); +        send_buff->commit(sizeof(data)); +    } -    //setup RX DSP regs -    std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl; -    _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, get_max_recv_samps_per_packet()); -    _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); -    _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset -    _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 -        | (0x1 << 28) //if data with stream id -        | (0x1 << 26) //has trailer -        | (0x3 << 22) //integer time other -        | (0x1 << 20) //fractional time sample count -    ); -    _iface->poke32(U2_REG_RX_CTRL_VRT_STREAM_ID, 0); -    _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0); +    //setup VRT RX DSP regs +    for(size_t i = 0; i < _mboards.size(); i++){ +        _mboards[i]->setup_vrt_recv_regs(get_max_recv_samps_per_packet()); +    } +    std::cout << "RX samples per packet: " << get_max_recv_samps_per_packet() << std::endl;      std::cout << "TX samples per packet: " << get_max_send_samps_per_packet() << std::endl;      //create new io impl -    _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); +    _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transports));  }  /***********************************************************************   * Send Data   **********************************************************************/ -bool tmp_todo_fixme_remove_get_send_buffs(vrt_packet_handler::managed_send_buffs_t &buffs, const zero_copy_if::sptr &zc_if){ -    buffs[0] = zc_if->get_send_buff(); -    return buffs[0].get() != NULL; +bool get_send_buffs( +    const std::vector<udp_zero_copy::sptr> &trans, +    vrt_packet_handler::managed_send_buffs_t &buffs +){ +    UHD_ASSERT_THROW(trans.size() == buffs.size()); +    for (size_t i = 0; i < buffs.size(); i++){ +        buffs[i] = trans[i]->get_send_buff(); +    } +    return true;  }  size_t usrp2_impl::send(      const std::vector<const void *> &buffs, -    size_t nsamps_per_buff, +    size_t num_samps,      const tx_metadata_t &metadata,      const io_type_t &io_type,      send_mode_t send_mode  ){      return vrt_packet_handler::send(          _io_impl->packet_handler_send_state, //last state of the send handler -        buffs, nsamps_per_buff,     //buffer to empty +        buffs, num_samps,           //buffer to fill          metadata, send_mode,        //samples metadata          io_type, _tx_otw_type,      //input and output types to convert          get_master_clock_freq(),    //master clock tick rate          uhd::transport::vrt::if_hdr_pack_be, -        boost::bind(&tmp_todo_fixme_remove_get_send_buffs, _1, _data_transport), +        boost::bind(&get_send_buffs, _data_transports, _1),          get_max_send_samps_per_packet()      );  } @@ -157,25 +161,20 @@ size_t usrp2_impl::send(  /***********************************************************************   * Receive Data   **********************************************************************/ -bool tmp_todo_fixme_remove_get_recv_buffs(vrt_packet_handler::managed_recv_buffs_t &buffs, boost::shared_ptr<usrp2_impl::io_impl> impl){ -    buffs[0] = impl->get_recv_buff(); -    return buffs[0].get() != NULL; -} -  size_t usrp2_impl::recv(      const std::vector<void *> &buffs, -    size_t nsamps_per_buff, +    size_t num_samps,      rx_metadata_t &metadata,      const io_type_t &io_type,      recv_mode_t recv_mode  ){      return vrt_packet_handler::recv(          _io_impl->packet_handler_recv_state, //last state of the recv handler -        buffs, nsamps_per_buff,     //buffer to empty +        buffs, num_samps,           //buffer to fill          metadata, recv_mode,        //samples metadata          io_type, _rx_otw_type,      //input and output types to convert          get_master_clock_freq(),    //master clock tick rate          uhd::transport::vrt::if_hdr_unpack_be, -        boost::bind(&tmp_todo_fixme_remove_get_recv_buffs, _1, _io_impl) +        boost::bind(&usrp2_impl::io_impl::get_recv_buffs, _io_impl, _1)      );  } diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index 2c900b328..903d5da86 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -30,16 +30,70 @@ using namespace uhd;  using namespace uhd::usrp;  /*********************************************************************** + * Structors + **********************************************************************/ +usrp2_mboard_impl::usrp2_mboard_impl( +    size_t index, transport::udp_simple::sptr ctrl_transport +): +    _index(index) +{ +    //make a new interface for usrp2 stuff +    _iface = usrp2_iface::make(ctrl_transport); +    _clock_ctrl = usrp2_clock_ctrl::make(_iface); +    _codec_ctrl = usrp2_codec_ctrl::make(_iface); +    _serdes_ctrl = usrp2_serdes_ctrl::make(_iface); + +    //TODO move to dsp impl... +    //load the allowed decim/interp rates +    //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) +    _allowed_decim_and_interp_rates.clear(); +    for (size_t i = 4; i <= 128; i+=1){ +        _allowed_decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 130; i <= 256; i+=2){ +        _allowed_decim_and_interp_rates.push_back(i); +    } +    for (size_t i = 260; i <= 512; i+=4){ +        _allowed_decim_and_interp_rates.push_back(i); +    } + +    //init the ddc +    init_ddc_config(); + +    //init the duc +    init_duc_config(); + +    //initialize the clock configuration +    init_clock_config(); + +    //init the tx and rx dboards (do last) +    dboard_init(); +} + +usrp2_mboard_impl::~usrp2_mboard_impl(void){ +    /* NOP */ +} + +/***********************************************************************   * Helper Methods   **********************************************************************/ -void usrp2_impl::mboard_init(void){ -    _mboard_proxy = wax_obj_proxy::make( -        boost::bind(&usrp2_impl::mboard_get, this, _1, _2), -        boost::bind(&usrp2_impl::mboard_set, this, _1, _2) +void usrp2_mboard_impl::setup_vrt_recv_regs(size_t num_samps){ +    _max_recv_samps_per_packet = num_samps; +     +    _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _max_recv_samps_per_packet); +    _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); +    _iface->poke32(U2_REG_RX_CTRL_CLEAR_OVERRUN, 1); //reset +    _iface->poke32(U2_REG_RX_CTRL_VRT_HEADER, 0 +        | (0x1 << 28) //if data with stream id +        | (0x1 << 26) //has trailer +        | (0x3 << 22) //integer time other +        | (0x1 << 20) //fractional time sample count      ); +    _iface->poke32(U2_REG_RX_CTRL_VRT_STREAM_ID, 0); +    _iface->poke32(U2_REG_RX_CTRL_VRT_TRAILER, 0);  } -void usrp2_impl::init_clock_config(void){ +void usrp2_mboard_impl::init_clock_config(void){      //setup the clock configuration settings      _clock_config.ref_source = clock_config_t::REF_INT;      _clock_config.pps_source = clock_config_t::PPS_SMA; @@ -49,7 +103,7 @@ void usrp2_impl::init_clock_config(void){      update_clock_config();  } -void usrp2_impl::update_clock_config(void){ +void usrp2_mboard_impl::update_clock_config(void){      boost::uint32_t pps_flags = 0;      //translate pps source enums @@ -82,7 +136,7 @@ void usrp2_impl::update_clock_config(void){      _clock_ctrl->enable_external_ref(use_external);  } -void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){ +void usrp2_mboard_impl::set_time_spec(const time_spec_t &time_spec, bool now){      //set the ticks      _iface->poke32(U2_REG_TIME64_TICKS, time_spec.get_tick_count(get_master_clock_freq())); @@ -94,7 +148,7 @@ void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){      _iface->poke32(U2_REG_TIME64_SECS, boost::uint32_t(time_spec.get_full_secs()));  } -void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){ +void usrp2_mboard_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){      UHD_ASSERT_THROW(stream_cmd.num_samps <= U2_REG_RX_CTRL_MAX_SAMPS_PER_CMD);      //setup the mode to instruction flags @@ -113,7 +167,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){      //issue the stream command      _iface->poke32(U2_REG_RX_CTRL_STREAM_CMD, U2_REG_RX_CTRL_MAKE_CMD( -        (inst_samps)? stream_cmd.num_samps : ((inst_chain)? get_max_recv_samps_per_packet() : 1), +        (inst_samps)? stream_cmd.num_samps : ((inst_chain)? _max_recv_samps_per_packet : 1),          (stream_cmd.stream_now)? 1 : 0,          (inst_chain)? 1 : 0,          (inst_reload)? 1 : 0 @@ -125,7 +179,7 @@ void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){  /***********************************************************************   * MBoard Get Properties   **********************************************************************/ -void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){ +void usrp2_mboard_impl::get(const wax::obj &key_, wax::obj &val){      wax::obj key; std::string name;      boost::tie(key, name) = extract_named_prop(key_); @@ -148,7 +202,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){      //handle the get request conditioned on the key      switch(key.as<mboard_prop_t>()){      case MBOARD_PROP_NAME: -        val = std::string("usrp2 mboard"); +        val = str(boost::format("usrp2 mboard %d") % _index);          return;      case MBOARD_PROP_OTHERS:{ @@ -207,7 +261,7 @@ void usrp2_impl::mboard_get(const wax::obj &key_, wax::obj &val){  /***********************************************************************   * MBoard Set Properties   **********************************************************************/ -void usrp2_impl::mboard_set(const wax::obj &key, const wax::obj &val){ +void usrp2_mboard_impl::set(const wax::obj &key, const wax::obj &val){      //handle the other props      if (key.type() == typeid(std::string)){          if (key.as<std::string>() == "mac-addr"){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 36c264c3c..af496bf69 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -21,6 +21,7 @@  #include <uhd/usrp/device_props.hpp>  #include <uhd/utils/assert.hpp>  #include <uhd/utils/static.hpp> +#include <boost/algorithm/string.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp>  #include <boost/foreach.hpp> @@ -39,6 +40,15 @@ UHD_STATIC_BLOCK(register_usrp2_device){  }  /*********************************************************************** + * Helper Functions + **********************************************************************/ +std::vector<std::string> split_addrs(const std::string &addrs_str){ +    std::vector<std::string> addrs; +    boost::split(addrs, addrs_str, boost::is_any_of("\t ")); +    return addrs; +} + +/***********************************************************************   * Discovery over the udp transport   **********************************************************************/  uhd::device_addrs_t usrp2::find(const device_addr_t &hint){ @@ -66,6 +76,16 @@ uhd::device_addrs_t usrp2::find(const device_addr_t &hint){          return usrp2_addrs;      } +    //if there are multiple addresses, just return good, dont test +    std::vector<std::string> addrs = split_addrs(hint["addr"]); +    if (addrs.size() > 1){ +        device_addr_t new_addr; +        new_addr["type"] = "usrp2"; +        new_addr["addr"] = hint["addr"]; +        usrp2_addrs.push_back(new_addr); +        return usrp2_addrs; +    } +      //create a udp transport to communicate      std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT);      udp_simple::sptr udp_transport = udp_simple::make_broadcast( @@ -112,11 +132,6 @@ template <class T> std::string num2str(T num){  }  device::sptr usrp2::make(const device_addr_t &device_addr){ -    //create a control transport -    udp_simple::sptr ctrl_transport = udp_simple::make_connected( -        device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT) -    ); -      //extract the receive and send buffer sizes      size_t recv_buff_size = 0, send_buff_size= 0 ;      if (device_addr.has_key("recv_buff_size")){ @@ -126,17 +141,23 @@ device::sptr usrp2::make(const device_addr_t &device_addr){          send_buff_size = size_t(boost::lexical_cast<double>(device_addr["send_buff_size"]));      } -    //create a data transport -    udp_zero_copy::sptr data_transport = udp_zero_copy::make( -        device_addr["addr"], -        num2str(USRP2_UDP_DATA_PORT), -        recv_buff_size, -        send_buff_size -    ); +    //create a ctrl and data transport for each address +    std::vector<udp_simple::sptr> ctrl_transports; +    std::vector<udp_zero_copy::sptr> data_transports; + +    BOOST_FOREACH(const std::string &addr, split_addrs(device_addr["addr"])){ +        ctrl_transports.push_back(udp_simple::make_connected( +            addr, num2str(USRP2_UDP_CTRL_PORT) +        )); +        data_transports.push_back(udp_zero_copy::make( +            addr, num2str(USRP2_UDP_DATA_PORT), +            recv_buff_size, send_buff_size +        )); +    }      //create the usrp2 implementation guts      return device::sptr( -        new usrp2_impl(ctrl_transport, data_transport) +        new usrp2_impl(ctrl_transports, data_transports)      );  } @@ -144,44 +165,20 @@ device::sptr usrp2::make(const device_addr_t &device_addr){   * Structors   **********************************************************************/  usrp2_impl::usrp2_impl( -    udp_simple::sptr ctrl_transport, -    udp_zero_copy::sptr data_transport -){ -    _data_transport = data_transport; - -    //make a new interface for usrp2 stuff -    _iface = usrp2_iface::make(ctrl_transport); -    _clock_ctrl = usrp2_clock_ctrl::make(_iface); -    _codec_ctrl = usrp2_codec_ctrl::make(_iface); -    _serdes_ctrl = usrp2_serdes_ctrl::make(_iface); - -    //load the allowed decim/interp rates -    //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4) -    _allowed_decim_and_interp_rates.clear(); -    for (size_t i = 4; i <= 128; i+=1){ -        _allowed_decim_and_interp_rates.push_back(i); -    } -    for (size_t i = 130; i <= 256; i+=2){ -        _allowed_decim_and_interp_rates.push_back(i); +    std::vector<udp_simple::sptr> ctrl_transports, +    std::vector<udp_zero_copy::sptr> data_transports +): +    _data_transports(data_transports) +{ +    //create a new mboard handler for each control transport +    for(size_t i = 0; i < ctrl_transports.size(); i++){ +        _mboards.push_back(usrp2_mboard_impl::sptr( +            new usrp2_mboard_impl(i, ctrl_transports[i]) +        )); +        //use an empty name when there is only one mboard +        std::string name = (ctrl_transports.size() > 1)? boost::lexical_cast<std::string>(i) : ""; +        _mboard_dict[name] = _mboards.back();      } -    for (size_t i = 260; i <= 512; i+=4){ -        _allowed_decim_and_interp_rates.push_back(i); -    } - -    //init the mboard -    mboard_init(); - -    //init the ddc -    init_ddc_config(); - -    //init the duc -    init_duc_config(); - -    //initialize the clock configuration -    init_clock_config(); - -    //init the tx and rx dboards (do last) -    dboard_init();      //init the send and recv io      io_init(); @@ -206,12 +203,11 @@ void usrp2_impl::get(const wax::obj &key_, wax::obj &val){          return;      case DEVICE_PROP_MBOARD: -        UHD_ASSERT_THROW(name == ""); -        val = _mboard_proxy->get_link(); +        val = _mboard_dict[name]->get_link();          return;      case DEVICE_PROP_MBOARD_NAMES: -        val = prop_names_t(1, ""); +        val = prop_names_t(_mboard_dict.keys());          return;      default: UHD_THROW_PROP_GET_ERROR(); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 70735173e..ccda5e3d8 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -62,102 +62,50 @@ public:          return sptr(new wax_obj_proxy(get, set));      } -    ~wax_obj_proxy(void){ -        /* NOP */ -    } -  private: -    get_t _get; -    set_t _set; - -    wax_obj_proxy(const get_t &get, const set_t &set){ -        _get = get; -        _set = set; -    }; - -    void get(const wax::obj &key, wax::obj &val){ -        return _get(key, val); -    } - -    void set(const wax::obj &key, const wax::obj &val){ -        return _set(key, val); -    } +    get_t _get; set_t _set; +    wax_obj_proxy(const get_t &get, const set_t &set): _get(get), _set(set){}; +    void get(const wax::obj &key, wax::obj &val){return _get(key, val);} +    void set(const wax::obj &key, const wax::obj &val){return _set(key, val);}  };  /*! - * USRP2 implementation guts: + * USRP2 mboard implementation guts:   * The implementation details are encapsulated here.   * Handles properties on the mboard, dboard, dsps...   */ -class usrp2_impl : public uhd::device{ +class usrp2_mboard_impl : public wax::obj{  public: -    /*! -     * Create a new usrp2 impl base. -     * \param ctrl_transport the udp transport for control -     * \param data_transport the udp transport for data -     */ -    usrp2_impl( -        uhd::transport::udp_simple::sptr ctrl_transport, -        uhd::transport::udp_zero_copy::sptr data_transport -    ); +    typedef boost::shared_ptr<usrp2_mboard_impl> sptr; -    ~usrp2_impl(void); +    //structors +    usrp2_mboard_impl(size_t index, uhd::transport::udp_simple::sptr); +    ~usrp2_mboard_impl(void); -    //the io interface -    size_t get_max_send_samps_per_packet(void) const{ -        return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); -    } -    size_t send( -        const std::vector<const void *> &, size_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{ -        return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); -    } -    size_t recv( -        const std::vector<void *> &, size_t, -        uhd::rx_metadata_t &, -        const uhd::io_type_t &, -        uhd::device::recv_mode_t -    ); - -    UHD_PIMPL_DECL(io_impl) _io_impl; +    void setup_vrt_recv_regs(size_t num_samps); -private:      inline double get_master_clock_freq(void){          return _clock_ctrl->get_master_clock_rate();      } -    //device properties interface +    //properties for this mboard      void get(const wax::obj &, wax::obj &);      void set(const wax::obj &, const wax::obj &); +private: +    size_t _index; +    size_t _max_recv_samps_per_packet; +      //interfaces      usrp2_iface::sptr _iface;      usrp2_clock_ctrl::sptr _clock_ctrl;      usrp2_codec_ctrl::sptr _codec_ctrl;      usrp2_serdes_ctrl::sptr _serdes_ctrl; -    /******************************************************************* -     * Deal with the rx and tx packet sizes -     ******************************************************************/ -    static const size_t _max_rx_bytes_per_packet = -        USRP2_UDP_BYTES - -        USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) - -        USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t) -    ; -    static const size_t _max_tx_bytes_per_packet = -        USRP2_UDP_BYTES - -        uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) -    ; - -    uhd::otw_type_t _rx_otw_type, _tx_otw_type; -    void io_init(void); - -    //udp transports for control and data -    uhd::transport::udp_zero_copy::sptr _data_transport; +    //rx and tx dboard methods and objects +    uhd::usrp::dboard_manager::sptr _dboard_manager; +    uhd::usrp::dboard_iface::sptr _dboard_iface; +    void dboard_init(void);      //methods and shadows for clock configuration      uhd::clock_config_t _clock_config; @@ -165,17 +113,6 @@ private:      void update_clock_config(void);      void set_time_spec(const uhd::time_spec_t &time_spec, bool now); -    //rx and tx dboard methods and objects -    uhd::usrp::dboard_manager::sptr _dboard_manager; -    uhd::usrp::dboard_iface::sptr _dboard_iface; -    void dboard_init(void); - -    //properties for the mboard -    void mboard_init(void); -    void mboard_get(const wax::obj &, wax::obj &); -    void mboard_set(const wax::obj &, const wax::obj &); -    wax_obj_proxy::sptr _mboard_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 &); @@ -214,4 +151,76 @@ private:  }; +/*! + * USRP2 implementation guts: + * The implementation details are encapsulated here. + * Handles device properties and streaming... + */ +class usrp2_impl : public uhd::device{ +public: +    /*! +     * Create a new usrp2 impl base. +     * \param ctrl_transports the udp transports for control +     * \param data_transports the udp transports for data +     */ +    usrp2_impl( +        std::vector<uhd::transport::udp_simple::sptr> ctrl_transports, +        std::vector<uhd::transport::udp_zero_copy::sptr> data_transports +    ); + +    ~usrp2_impl(void); + +    //the io interface +    size_t get_max_send_samps_per_packet(void) const{ +        return _max_tx_bytes_per_packet/_tx_otw_type.get_sample_size(); +    } +    size_t send( +        const std::vector<const void *> &, size_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{ +        return _max_rx_bytes_per_packet/_rx_otw_type.get_sample_size(); +    } +    size_t recv( +        const std::vector<void *> &, size_t, +        uhd::rx_metadata_t &, +        const uhd::io_type_t &, +        uhd::device::recv_mode_t +    ); + +private: +    inline double get_master_clock_freq(void){ +        return _mboards.front()->get_master_clock_freq(); +    } + +    //device properties interface +    void get(const wax::obj &, wax::obj &); +    void set(const wax::obj &, const wax::obj &); + +    //pointers to mboards on this device (think mimo setup) +    std::vector<usrp2_mboard_impl::sptr> _mboards; +    uhd::dict<std::string, usrp2_mboard_impl::sptr> _mboard_dict; + +    /******************************************************************* +     * Deal with the rx and tx packet sizes +     ******************************************************************/ +    static const size_t _max_rx_bytes_per_packet = +        USRP2_UDP_BYTES - +        USRP2_HOST_RX_VRT_HEADER_WORDS32*sizeof(boost::uint32_t) - +        USRP2_HOST_RX_VRT_TRAILER_WORDS32*sizeof(boost::uint32_t) +    ; +    static const size_t _max_tx_bytes_per_packet = +        USRP2_UDP_BYTES - +        uhd::transport::vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - +        sizeof(uhd::transport::vrt::if_packet_info_t::cid) //no class id ever used +    ; + +    std::vector<uhd::transport::udp_zero_copy::sptr> _data_transports; +    uhd::otw_type_t _rx_otw_type, _tx_otw_type; +    UHD_PIMPL_DECL(io_impl) _io_impl; +    void io_init(void); +}; +  #endif /* INCLUDED_USRP2_IMPL_HPP */ | 
