diff options
Diffstat (limited to 'host/lib')
| -rw-r--r-- | host/lib/usrp/b100/b100_impl.cpp | 18 | ||||
| -rw-r--r-- | host/lib/usrp/b100/b100_impl.hpp | 23 | ||||
| -rw-r--r-- | host/lib/usrp/b100/io_impl.cpp | 222 | 
3 files changed, 151 insertions, 112 deletions
diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 98c5cab8c..d1928735b 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -297,8 +297,9 @@ b100_impl::b100_impl(const 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(&b100_impl::update_rx_samp_rate, this, _1)); +            .subscribe(boost::bind(&b100_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") @@ -317,8 +318,9 @@ b100_impl::b100_impl(const 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(&b100_impl::update_tx_samp_rate, this, _1)); +        .subscribe(boost::bind(&b100_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") @@ -402,16 +404,10 @@ b100_impl::b100_impl(const 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(&b100_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(&b100_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/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 5ec3dde7b..fb440e8be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -33,7 +33,6 @@  #include <uhd/property_tree.hpp>  #include <uhd/utils/pimpl.hpp>  #include <uhd/types/dict.hpp> -#include <uhd/types/otw_type.hpp>  #include <uhd/types/sensors.hpp>  #include <uhd/types/clock_config.hpp>  #include <uhd/types/stream_cmd.hpp> @@ -69,17 +68,8 @@ public:      ~b100_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); -    size_t get_max_send_samps_per_packet(void) const; -    size_t get_max_recv_samps_per_packet(void) const; +    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);  private: @@ -106,7 +96,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); @@ -115,14 +104,18 @@ private:          return _tree;      } +    std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers; +    std::vector<boost::weak_ptr<uhd::tx_streamer> > _tx_streamers; +      void check_fw_compat(void);      void check_fpga_compat(void);      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/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index d2eee4f7c..82298dca6 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -30,6 +30,7 @@  #include <boost/thread.hpp>  #include <uhd/utils/msg.hpp>  #include <uhd/utils/log.hpp> +#include <boost/make_shared.hpp>  using namespace uhd;  using namespace uhd::usrp; @@ -46,8 +47,6 @@ struct b100_impl::io_impl{      zero_copy_if::sptr data_transport;      bounded_buffer<async_metadata_t> async_msg_fifo;      recv_packet_demuxer::sptr demuxer; -    sph::recv_packet_handler recv_handler; -    sph::send_packet_handler send_handler;  };  /*********************************************************************** @@ -55,16 +54,6 @@ struct b100_impl::io_impl{   **********************************************************************/  void b100_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; -      //clear state machines      _fpga_ctrl->poke32(B100_REG_CLEAR_RX, 0);      _fpga_ctrl->poke32(B100_REG_CLEAR_TX, 0); @@ -72,19 +61,16 @@ void b100_impl::io_init(void){      //set the expected packet size in USB frames      _fpga_ctrl->poke32(B100_REG_MISC_RX_LEN, 4); +    //allocate streamer weak ptrs containers +    _rx_streamers.resize(_rx_dsps.size()); +    _tx_streamers.resize(1/*known to be 1 dsp*/); +      //create new io impl      _io_impl = UHD_PIMPL_MAKE(io_impl, ());      _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), B100_RX_SID_BASE);      //now its safe to register the async callback      _fpga_ctrl->set_async_cb(boost::bind(&b100_impl::handle_async_message, this, _1)); - -    //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 b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){ @@ -120,27 +106,54 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){      else UHD_MSG(error) << "Unknown async packet" << std::endl;  } +void b100_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 b100_impl::update_tick_rate(const double 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 b100_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 b100_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 b100_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 b100_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 b100_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 @@ -154,22 +167,9 @@ void b100_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 b100_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 @@ -178,16 +178,6 @@ void b100_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 -        )); -    }  }  /*********************************************************************** @@ -201,50 +191,110 @@ bool b100_impl::recv_async_msg(  }  /*********************************************************************** - * Send Data + * Receive streamer   **********************************************************************/ -size_t b100_impl::get_max_send_samps_per_packet(void) const { +rx_streamer::sptr b100_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      ; -    static const size_t bpp = 2048 - hdr_size; -    return bpp / _tx_otw_type.get_sample_size(); -} +    const size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer 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 b100_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;  }  /*********************************************************************** - * Receive Data + * Transmit streamer   **********************************************************************/ -size_t b100_impl::get_max_recv_samps_per_packet(void) const { +tx_streamer::sptr b100_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 = 2048 - hdr_size; //limited by FPGA pkt buffer size -    return bpp/_rx_otw_type.get_sample_size(); -} +    static const size_t bpp = 2048 - 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 b100_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(); + +    return my_streamer;  }  | 
