diff options
author | Josh Blum <josh@joshknows.com> | 2011-10-11 14:54:02 -0700 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2011-11-03 20:37:12 -0700 |
commit | ba0323c616e032ebde12073521c754d93c65f821 (patch) | |
tree | 2f92a2b85ad2560875d2c3a9b4d9de092860267e | |
parent | 5538048873f140f3ac2bbab12dc5b0729f68f1a5 (diff) | |
download | uhd-ba0323c616e032ebde12073521c754d93c65f821.tar.gz uhd-ba0323c616e032ebde12073521c754d93c65f821.tar.bz2 uhd-ba0323c616e032ebde12073521c754d93c65f821.zip |
b100: performed streamer API update to b100 impl
-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; } |