diff options
| author | Josh Blum <josh@joshknows.com> | 2011-10-11 17:46:44 -0700 | 
|---|---|---|
| committer | Josh Blum <josh@joshknows.com> | 2011-11-03 20:37:12 -0700 | 
| commit | 9fc513c961775c9682123394fe5d42ef914bbbd6 (patch) | |
| tree | b6a8312bcdf875ebda4bf14da2a501cc4ca63094 | |
| parent | ba0323c616e032ebde12073521c754d93c65f821 (diff) | |
| download | uhd-9fc513c961775c9682123394fe5d42ef914bbbd6.tar.gz uhd-9fc513c961775c9682123394fe5d42ef914bbbd6.tar.bz2 uhd-9fc513c961775c9682123394fe5d42ef914bbbd6.zip  | |
e100: performed streamer API update to e100 impl
| -rw-r--r-- | host/lib/usrp/b100/b100_impl.hpp | 1 | ||||
| -rw-r--r-- | host/lib/usrp/e100/e100_impl.cpp | 18 | ||||
| -rw-r--r-- | host/lib/usrp/e100/e100_impl.hpp | 18 | ||||
| -rw-r--r-- | host/lib/usrp/e100/io_impl.cpp | 241 | 
4 files changed, 162 insertions, 116 deletions
diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index fb440e8be..25badc967 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -41,6 +41,7 @@  #include <uhd/usrp/dboard_eeprom.hpp>  #include <uhd/usrp/dboard_manager.hpp>  #include <uhd/transport/usb_zero_copy.hpp> +#include <boost/weak_ptr.hpp>  static const double          B100_LINK_RATE_BPS = 256e6/8; //pratical link rate (< 480 Mbps)  static const std::string     B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 564a05a7e..deb52b2d7 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -271,8 +271,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){              .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1));          fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);          _tree->create<double>(rx_dsp_path / "rate/value") +            .set(1e6) //some default              .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) -            .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, _1)); +            .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, dspno, _1));          _tree->create<double>(rx_dsp_path / "freq/value")              .coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1));          _tree->create<meta_range_t>(rx_dsp_path / "freq/range") @@ -291,8 +292,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){      _tree->access<double>(mb_path / "tick_rate")          .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1));      _tree->create<double>(mb_path / "tx_dsps/0/rate/value") +        .set(1e6) //some default          .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) -        .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, _1)); +        .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, 0, _1));      _tree->create<double>(mb_path / "tx_dsps/0/freq/value")          .coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1));      _tree->create<meta_range_t>(mb_path / "tx_dsps/0/freq/range") @@ -376,16 +378,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){      ////////////////////////////////////////////////////////////////////      // do some post-init tasks      //////////////////////////////////////////////////////////////////// -    _tree->access<double>(mb_path / "tick_rate").update() //update and then subscribe the clock callback -        .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); +    this->update_rates(); -    //and now that the tick rate is set, init the host rates to something -    BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ -        _tree->access<double>(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); -    } -    BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ -        _tree->access<double>(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); -    } +    _tree->access<double>(mb_path / "tick_rate") //now subscribe the clock rate setter +        .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1));      _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0]));      _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index 4b2ec5ee0..954d6bd93 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -33,11 +33,10 @@  #include <uhd/usrp/mboard_eeprom.hpp>  #include <uhd/usrp/gps_ctrl.hpp>  #include <uhd/types/sensors.hpp> -#include <uhd/types/otw_type.hpp> -#include <uhd/types/clock_config.hpp>  #include <uhd/types/stream_cmd.hpp>  #include <uhd/usrp/dboard_manager.hpp>  #include <uhd/transport/zero_copy.hpp> +#include <boost/weak_ptr.hpp>  #ifndef INCLUDED_E100_IMPL_HPP  #define INCLUDED_E100_IMPL_HPP @@ -78,11 +77,9 @@ public:      ~e100_impl(void);      //the io interface -    size_t send(const send_buffs_type &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); -    size_t recv(const recv_buffs_type &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); +    uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); +    uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args);      bool recv_async_msg(uhd::async_metadata_t &, double); -    size_t get_max_send_samps_per_packet(void) const; -    size_t get_max_recv_samps_per_packet(void) const;  private:      uhd::property_tree::sptr _tree; @@ -110,7 +107,6 @@ private:      uhd::usrp::dboard_iface::sptr _dboard_iface;      //handle io stuff -    uhd::otw_type_t _rx_otw_type, _tx_otw_type;      UHD_PIMPL_DECL(io_impl) _io_impl;      void io_init(void); @@ -119,12 +115,16 @@ private:          return _tree;      } +    std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers; +    std::vector<boost::weak_ptr<uhd::tx_streamer> > _tx_streamers; +      double update_rx_codec_gain(const double); //sets A and B at once      void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &);      void set_db_eeprom(const std::string &, const uhd::usrp::dboard_eeprom_t &);      void update_tick_rate(const double rate); -    void update_rx_samp_rate(const double rate); -    void update_tx_samp_rate(const double rate); +    void update_rx_samp_rate(const size_t, const double rate); +    void update_tx_samp_rate(const size_t, const double rate); +    void update_rates(void);      void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &);      void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &);      void update_clock_source(const std::string &); diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 0b81c1a86..5936ee2d7 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -35,6 +35,7 @@  #include <fcntl.h> //open, close  #include <sstream>  #include <fstream> +#include <boost/make_shared.hpp>  using namespace uhd;  using namespace uhd::usrp; @@ -60,10 +61,6 @@ struct e100_impl::io_impl{      //which is after the states and booty which may hold managed buffers.      recv_packet_demuxer::sptr demuxer; -    //state management for the vrt packet handler code -    sph::recv_packet_handler recv_handler; -    sph::send_packet_handler send_handler; -      //a pirate's life is the life for me!      void recv_pirate_loop(          spi_iface::sptr //keep a sptr to iface which shares gpio147 @@ -159,16 +156,6 @@ void e100_impl::io_impl::handle_irq(void){   **********************************************************************/  void e100_impl::io_init(void){ -    //setup rx otw type -    _rx_otw_type.width = 16; -    _rx_otw_type.shift = 0; -    _rx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; - -    //setup tx otw type -    _tx_otw_type.width = 16; -    _tx_otw_type.shift = 0; -    _tx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; -      //create new io impl      _io_impl = UHD_PIMPL_MAKE(io_impl, ());      _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE); @@ -178,6 +165,10 @@ void e100_impl::io_init(void){      _fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0);      _fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0); +    //allocate streamer weak ptrs containers +    _rx_streamers.resize(_rx_dsps.size()); +    _tx_streamers.resize(1/*known to be 1 dsp*/); +      //prepare the async msg buffer for incoming messages      _fpga_ctrl->poke32(E100_REG_SR_ERR_CTRL, 1 << 0); //clear      while ((_fpga_ctrl->peek32(E100_REG_RB_ERR_STATUS) & (1 << 2)) == 0){} //wait for idle @@ -187,37 +178,58 @@ void e100_impl::io_init(void){      _io_impl->pirate_task = task::make(boost::bind(          &e100_impl::io_impl::recv_pirate_loop, _io_impl.get(), _aux_spi_iface      )); - -    //init some handler stuff -    _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_le); -    _io_impl->recv_handler.set_converter(_rx_otw_type); -    _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_le); -    _io_impl->send_handler.set_converter(_tx_otw_type); -    _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet());  }  void e100_impl::update_tick_rate(const double rate){      _io_impl->tick_rate = rate; -    boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); -    _io_impl->recv_handler.set_tick_rate(rate); -    boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); -    _io_impl->send_handler.set_tick_rate(rate); + +    //update the tick rate on all existing streamers -> thread safe +    for (size_t i = 0; i < _rx_streamers.size(); i++){ +        boost::shared_ptr<sph::recv_packet_streamer> my_streamer = +            boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[i].lock()); +        if (my_streamer.get() == NULL) continue; +        my_streamer->set_tick_rate(rate); +    } +    for (size_t i = 0; i < _tx_streamers.size(); i++){ +        boost::shared_ptr<sph::send_packet_streamer> my_streamer = +            boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[i].lock()); +        if (my_streamer.get() == NULL) continue; +        my_streamer->set_tick_rate(rate); +    }  } -void e100_impl::update_rx_samp_rate(const double rate){ -    boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); -    _io_impl->recv_handler.set_samp_rate(rate); -    const double adj = _rx_dsps.front()->get_scaling_adjustment(); -    _io_impl->recv_handler.set_scale_factor(adj/32767.); +void e100_impl::update_rx_samp_rate(const size_t dspno, const double rate){ +    boost::shared_ptr<sph::recv_packet_streamer> my_streamer = +        boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_rx_streamers[dspno].lock()); +    if (my_streamer.get() == NULL) return; + +    my_streamer->set_samp_rate(rate); +    const double adj = _rx_dsps[dspno]->get_scaling_adjustment(); +    my_streamer->set_scale_factor(adj); +} + +void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){ +    boost::shared_ptr<sph::send_packet_streamer> my_streamer = +        boost::dynamic_pointer_cast<sph::send_packet_streamer>(_tx_streamers[dspno].lock()); +    if (my_streamer.get() == NULL) return; + +    my_streamer->set_samp_rate(rate);  } -void e100_impl::update_tx_samp_rate(const double rate){ -    boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); -    _io_impl->send_handler.set_samp_rate(rate); +void e100_impl::update_rates(void){ +    const fs_path mb_path = "/mboards/0"; +    _tree->access<double>(mb_path / "tick_rate").update(); + +    //and now that the tick rate is set, init the host rates to something +    BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ +        _tree->access<double>(mb_path / "rx_dsps" / name / "rate" / "value").update(); +    } +    BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ +        _tree->access<double>(mb_path / "tx_dsps" / name / "rate" / "value").update(); +    }  }  void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ -    boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock();      fs_path root = "/mboards/0/dboards";      //sanity checking @@ -231,22 +243,9 @@ void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){          _rx_dsps[i]->set_mux(conn, fe_swapped);      }      _rx_fe->set_mux(fe_swapped); - -    //resize for the new occupancy -    _io_impl->recv_handler.resize(spec.size()); - -    //bind new callbacks for the handler -    for (size_t i = 0; i < _io_impl->recv_handler.size(); i++){ -        _rx_dsps[i]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this -        _io_impl->recv_handler.set_xport_chan_get_buff(i, boost::bind( -            &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, i, _1 -        )); -        _io_impl->recv_handler.set_overflow_handler(i, boost::bind(&rx_dsp_core_200::handle_overflow, _rx_dsps[i])); -    }  }  void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ -    boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock();      fs_path root = "/mboards/0/dboards";      //sanity checking @@ -255,73 +254,123 @@ void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){      //set the mux for this spec      const std::string conn = _tree->access<std::string>(root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection").get();      _tx_fe->set_mux(conn); +} -    //resize for the new occupancy -    _io_impl->send_handler.resize(spec.size()); - -    //bind new callbacks for the handler -    for (size_t i = 0; i < _io_impl->send_handler.size(); i++){ -        _io_impl->send_handler.set_xport_chan_get_buff(i, boost::bind( -            &zero_copy_if::get_send_buff, _data_transport, _1 -        )); -    } +/*********************************************************************** + * Async Recv + **********************************************************************/ +bool e100_impl::recv_async_msg( +    async_metadata_t &async_metadata, double timeout +){ +    boost::this_thread::disable_interruption di; //disable because the wait can throw +    return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout);  }  /*********************************************************************** - * Data Send + * Receive streamer   **********************************************************************/ -size_t e100_impl::get_max_send_samps_per_packet(void) const{ +rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ +    stream_args_t args = args_; + +    //setup defaults for unspecified values +    args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; +    args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; + +    //calculate packet size      static const size_t hdr_size = 0          + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) +        + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used      ; -    size_t bpp = _data_transport->get_send_frame_size() - hdr_size; -    return bpp/_tx_otw_type.get_sample_size(); -} +    const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; +    const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + +    //make the new streamer given the samples per packet +    boost::shared_ptr<sph::recv_packet_streamer> my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp); + +    //init some streamer stuff +    my_streamer->resize(args.channels.size()); +    my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_le); + +    //set the converter +    uhd::convert::id_type id; +    id.input_markup = args.otw_format + "_item32_le"; +    id.num_inputs = 1; +    id.output_markup = args.cpu_format; +    id.num_outputs = 1; +    id.args = args.args; +    my_streamer->set_converter(id); + +    //bind callbacks for the handler +    for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ +        const size_t dsp = args.channels[chan_i]; +        _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this +        _rx_dsps[dsp]->set_format(args.otw_format, 0x400); +        my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( +            &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 +        )); +        my_streamer->set_overflow_handler(chan_i, boost::bind( +            &rx_dsp_core_200::handle_overflow, _rx_dsps[dsp] +        )); +        _rx_streamers[dsp] = my_streamer; //store weak pointer +    } -size_t e100_impl::send( -    const send_buffs_type &buffs, size_t nsamps_per_buff, -    const tx_metadata_t &metadata, const io_type_t &io_type, -    send_mode_t send_mode, double timeout -){ -    return _io_impl->send_handler.send( -        buffs, nsamps_per_buff, -        metadata, io_type, -        send_mode, timeout -    ); +    //sets all tick and samp rates on this streamer +    this->update_rates(); + +    return my_streamer;  }  /*********************************************************************** - * Data Recv + * Transmit streamer   **********************************************************************/ -size_t e100_impl::get_max_recv_samps_per_packet(void) const{ +tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ +    stream_args_t args = args_; + +    //setup defaults for unspecified values +    args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; +    args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; + +    if (args.otw_format != "sc16"){ +        throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); +    } + +    //calculate packet size      static const size_t hdr_size = 0          + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) -        + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used      ; -    size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; -    return bpp/_rx_otw_type.get_sample_size(); -} +    static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; +    const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + +    //make the new streamer given the samples per packet +    boost::shared_ptr<sph::send_packet_streamer> my_streamer = boost::make_shared<sph::send_packet_streamer>(spp); + +    //init some streamer stuff +    my_streamer->resize(args.channels.size()); +    my_streamer->set_vrt_packer(&vrt::if_hdr_pack_le); + +    //set the converter +    uhd::convert::id_type id; +    id.input_markup = args.cpu_format; +    id.num_inputs = 1; +    id.output_markup = args.otw_format + "_item32_le"; +    id.num_outputs = 1; +    id.args = args.args; +    my_streamer->set_converter(id); + +    //bind callbacks for the handler +    for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ +        const size_t dsp = args.channels[chan_i]; +        UHD_ASSERT_THROW(dsp == 0); //always 0 +        my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( +            &zero_copy_if::get_send_buff, _data_transport, _1 +        )); +        _tx_streamers[dsp] = my_streamer; //store weak pointer +    } -size_t e100_impl::recv( -    const recv_buffs_type &buffs, size_t nsamps_per_buff, -    rx_metadata_t &metadata, const io_type_t &io_type, -    recv_mode_t recv_mode, double timeout -){ -    return _io_impl->recv_handler.recv( -        buffs, nsamps_per_buff, -        metadata, io_type, -        recv_mode, timeout -    ); -} +    //sets all tick and samp rates on this streamer +    this->update_rates(); -/*********************************************************************** - * Async Recv - **********************************************************************/ -bool e100_impl::recv_async_msg( -    async_metadata_t &async_metadata, double timeout -){ -    boost::this_thread::disable_interruption di; //disable because the wait can throw -    return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout); +    return my_streamer;  }  | 
