From 66c95c12a1d2f7b79bdf5b9b871d1b957c56606f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 4 Oct 2011 18:08:47 -0700 Subject: uhd: lots of work releated to streamer work and usrp2 implementation --- host/lib/usrp/usrp2/io_impl.cpp | 270 +++++++++++++++++++++---------------- host/lib/usrp/usrp2/usrp2_impl.cpp | 20 +-- host/lib/usrp/usrp2/usrp2_impl.hpp | 27 ++-- 3 files changed, 172 insertions(+), 145 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 70331e536..98bfcdd3b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include using namespace uhd; @@ -158,10 +159,6 @@ struct usrp2_impl::io_impl{ std::vector tx_xports; std::vector fc_mons; - //state management for the vrt packet handler code - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; - //methods and variables for the pirate crew void recv_pirate_loop(zero_copy_if::sptr, size_t); std::list pirate_tasks; @@ -237,17 +234,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( * Helper Functions **********************************************************************/ void usrp2_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_BIG_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, ()); @@ -260,6 +246,12 @@ void usrp2_impl::io_init(void){ ))); } + //allocate streamer weak ptrs containers + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + _mbc[mb].rx_streamers.resize(_mbc[mb].rx_dsps.size()); + _mbc[mb].tx_streamers.resize(1/*known to be 1 dsp*/); + } + //create a new pirate thread for each zc if (yarr!!) size_t index = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ @@ -269,58 +261,68 @@ void usrp2_impl::io_init(void){ _mbc[mb].tx_dsp_xport, index++ ))); } - - //init some handler stuff - _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_be); - _io_impl->recv_handler.set_converter(_rx_otw_type); - _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); - _io_impl->send_handler.set_converter(_tx_otw_type); - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); - - //set the packet threshold to be an entire socket buffer's worth - const size_t packets_per_sock_buff = size_t(50e6/_mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); - _io_impl->recv_handler.set_alignment_failure_threshold(packets_per_sock_buff); } void usrp2_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); + _io_impl->tick_rate = rate; //shadow for async msg + + //update the tick rate on all existing streamers -> thread safe + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + for (size_t i = 0; i < _mbc[mb].rx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + my_streamer->set_tick_rate(rate); + } + for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + my_streamer->set_tick_rate(rate); + } + } } -void usrp2_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 = _mbc[_mbc.keys().front()].rx_dsps.front()->get_scaling_adjustment(); - _io_impl->recv_handler.set_scale_factor(adj/32767.); +void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) return; + + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + + my_streamer->set_samp_rate(rate); + const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj/32767.); } -void usrp2_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 usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) return; + + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + + my_streamer->set_samp_rate(rate); } -static subdev_spec_t replace_zero_in_spec(const std::string &type, const subdev_spec_t &spec){ - subdev_spec_t new_spec; - BOOST_FOREACH(const subdev_spec_pair_t &pair, spec){ - if (pair.db_name == "0"){ - UHD_MSG(warning) - << boost::format("In the %s subdevice specification: %s") % type % spec.to_string() << std::endl - << "Accepting dboard slot name \"0\" for backward compatibility." << std::endl - << "The official name of the dboard slot on USRP2/N-Series is \"A\"." << std::endl - ; - new_spec.push_back(subdev_spec_pair_t("A", pair.sd_name)); +void usrp2_impl::update_rates(void){ + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + fs_path root = "/mboards/" + mb; + _tree->access(root / "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(root / "rx_dsps")){ + _tree->access(root / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(root / "tx_dsps")){ + _tree->access(root / "tx_dsps" / name / "rate" / "value").update(); } - else new_spec.push_back(pair); } - return new_spec; } -subdev_spec_t usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){ - const subdev_spec_t spec = replace_zero_in_spec("RX", spec_); - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); +void usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ fs_path root = "/mboards/" + which_mb + "/dboards"; //sanity checking @@ -339,24 +341,9 @@ subdev_spec_t usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, con _mbc[which_mb].rx_chan_occ = spec.size(); size_t nchan = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].rx_chan_occ; - _io_impl->recv_handler.resize(nchan); - - //bind new callbacks for the handler - size_t chan = 0; - BOOST_FOREACH(const std::string &mb, _mbc.keys()){ - for (size_t dsp = 0; dsp < _mbc[mb].rx_chan_occ; dsp++){ - _mbc[mb].rx_dsps[dsp]->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(chan++, boost::bind( - &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 - )); - } - } - return spec; } -subdev_spec_t usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){ - const subdev_spec_t spec = replace_zero_in_spec("TX", spec_); - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); +void usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ fs_path root = "/mboards/" + which_mb + "/dboards"; //sanity checking @@ -370,18 +357,6 @@ subdev_spec_t usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, con _mbc[which_mb].tx_chan_occ = spec.size(); size_t nchan = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].tx_chan_occ; - _io_impl->send_handler.resize(nchan); - - //bind new callbacks for the handler - size_t chan = 0, i = 0; - BOOST_FOREACH(const std::string &mb, _mbc.keys()){ - for (size_t dsp = 0; dsp < _mbc[mb].tx_chan_occ; dsp++){ - _io_impl->send_handler.set_xport_chan_get_buff(chan++, boost::bind( - &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), i++, _1 - )); - } - } - return spec; } /*********************************************************************** @@ -395,51 +370,118 @@ bool usrp2_impl::recv_async_msg( } /*********************************************************************** - * Send Data + * Receive streamer **********************************************************************/ -size_t usrp2_impl::get_max_send_samps_per_packet(void) const{ +rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + vrt_send_header_offset_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 ; - const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; - return bpp/_tx_otw_type.get_sample_size(); -} + const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->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 my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(channels.size()); + my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_be); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_be"; + 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 < channels.size(); chan_i++){ + const size_t chan = channels[chan_i]; + size_t num_chan_so_far = 0; + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + num_chan_so_far += _mbc[mb].rx_chan_occ; + if (chan < num_chan_so_far){ + const size_t dsp = num_chan_so_far - chan - 1; + _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 + )); + _mbc[mb].rx_streamers[dsp] = my_streamer; //store weak pointer + break; + } + } + } -size_t usrp2_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 - ); + //set the packet threshold to be an entire socket buffer's worth + const size_t packets_per_sock_buff = size_t(50e6/_mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); + my_streamer->set_alignment_failure_threshold(packets_per_sock_buff); + + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } /*********************************************************************** - * Receive Data + * Transmit streamer **********************************************************************/ -size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{ +tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(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 + + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; - return bpp/_rx_otw_type.get_sample_size(); -} + const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->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 my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(channels.size()); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be); + + //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_be"; + 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 < channels.size(); chan_i++){ + const size_t chan = channels[chan_i]; + size_t num_chan_so_far = 0; + size_t abs = 0; + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + num_chan_so_far += _mbc[mb].tx_chan_occ; + if (chan < num_chan_so_far){ + const size_t dsp = num_chan_so_far - chan - 1; + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1 + )); + _mbc[mb].tx_streamers[dsp] = my_streamer; //store weak pointer + break; + } + abs += 1; //assume 1 tx dsp + } + } -size_t usrp2_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; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2b541bcf0..2d89ddaf4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -458,9 +458,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ ); //TODO lots of properties to expose here for frontends _tree->create(mb_path / "rx_subdev_spec") - .coerce(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); + .subscribe(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); _tree->create(mb_path / "tx_subdev_spec") - .coerce(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); + .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); //////////////////////////////////////////////////////////////// // create rx dsp control objects @@ -481,8 +481,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1)) - .subscribe(boost::bind(&usrp2_impl::update_rx_samp_rate, this, _1)); + .subscribe(boost::bind(&usrp2_impl::update_rx_samp_rate, this, mb, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _mbc[mb].rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -501,8 +502,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/rate/value") + .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) - .subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, _1)); + .subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, mb, 0, _1)); _tree->create(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&usrp2_impl::set_tx_dsp_freq, this, mb, _1)); _tree->create(mb_path / "tx_dsps/0/freq/range") @@ -594,17 +596,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ this->io_init(); //do some post-init tasks + this->update_rates(); BOOST_FOREACH(const std::string &mb, _mbc.keys()){ fs_path root = "/mboards/" + mb; - _tree->access(root / "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(root / "rx_dsps")){ - _tree->access(root / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(root / "tx_dsps")){ - _tree->access(root / "tx_dsps" / name / "rate" / "value").set(1e6); - } _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_rx_subdev_names()[0])); _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_tx_subdev_names()[0])); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 6f133f411..566c93853 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -73,18 +72,8 @@ public: ~usrp2_impl(void); //the io interface - size_t send( - const send_buffs_type &, size_t, - const uhd::tx_metadata_t &, const uhd::io_type_t &, - uhd::device::send_mode_t, double - ); - size_t recv( - const recv_buffs_type &, size_t, - uhd::rx_metadata_t &, const uhd::io_type_t &, - uhd::device::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_streamer(const uhd::streamer_args &args); + uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -97,6 +86,8 @@ private: rx_frontend_core_200::sptr rx_fe; tx_frontend_core_200::sptr tx_fe; std::vector rx_dsps; + std::vector > rx_streamers; + std::vector > tx_streamers; tx_dsp_core_200::sptr tx_dsp; time64_core_200::sptr time64; std::vector rx_dsp_xports; @@ -120,15 +111,15 @@ private: } //io impl methods and members - uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); 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 std::string &, const size_t, const double rate); + void update_tx_samp_rate(const std::string &, const size_t, const double rate); + void update_rates(void); //update spec methods are coercers until we only accept db_name == A - uhd::usrp::subdev_spec_t update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); - uhd::usrp::subdev_spec_t update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); + void update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); + void update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); double set_tx_dsp_freq(const std::string &, const double); uhd::meta_range_t get_tx_dsp_freq_range(const std::string &); void update_clock_source(const std::string &, const std::string &); -- cgit v1.2.3 From fbe2aefe299a4d3ddf8cceb0eb5866136f48744d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 11:54:36 -0700 Subject: usrp2: additional corrections for streaming to work --- host/lib/transport/super_send_packet_handler.hpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 6 +++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index edfe9bd13..87ae01d47 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -263,6 +263,7 @@ class send_packet_streamer : public send_packet_handler, public tx_streamer{ public: send_packet_streamer(const size_t max_num_samps){ _max_num_samps = max_num_samps; + this->set_max_samples_per_packet(_max_num_samps); } size_t get_num_channels(void) const{ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 98bfcdd3b..44217c36c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -298,8 +298,8 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co } void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); @@ -450,7 +450,7 @@ tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ //init some streamer stuff my_streamer->resize(channels.size()); - my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); //set the converter uhd::convert::id_type id; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 566c93853..a67c704c8 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -86,8 +86,8 @@ private: rx_frontend_core_200::sptr rx_fe; tx_frontend_core_200::sptr tx_fe; std::vector rx_dsps; - std::vector > rx_streamers; - std::vector > tx_streamers; + std::vector > rx_streamers; + std::vector > tx_streamers; tx_dsp_core_200::sptr tx_dsp; time64_core_200::sptr time64; std::vector rx_dsp_xports; -- cgit v1.2.3 From e4561a18cd4bbcf8a20799704c42bfb4c2543dc2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 14:41:57 -0700 Subject: usrp1: did work for stream interface on usrp1 --- host/lib/transport/super_recv_packet_handler.hpp | 9 - host/lib/transport/super_send_packet_handler.hpp | 9 - host/lib/usrp/usrp1/io_impl.cpp | 271 +++++++++++++++-------- host/lib/usrp/usrp1/usrp1_impl.cpp | 11 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 25 +-- host/lib/usrp/usrp2/io_impl.cpp | 6 - 6 files changed, 195 insertions(+), 136 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index f0b053473..f4dbc5531 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -135,11 +134,6 @@ public: _props.at(xport_chan).handle_overflow = handle_overflow; } - //! Get a scoped lock object for this instance - boost::mutex::scoped_lock get_scoped_lock(void){ - return boost::mutex::scoped_lock(_mutex); - } - //! Set the scale factor used in float conversion void set_scale_factor(const double scale_factor){ _scale_factor = scale_factor; @@ -156,8 +150,6 @@ public: uhd::rx_metadata_t &metadata, double timeout ){ - boost::mutex::scoped_lock lock(_mutex); - //handle metadata queued from a previous receive if (_queue_error_for_next_call){ _queue_error_for_next_call = false; @@ -197,7 +189,6 @@ public: private: - boost::mutex _mutex; vrt_unpacker_type _vrt_unpacker; size_t _header_offset_words32; double _tick_rate, _samp_rate; diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 87ae01d47..079fea11e 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -115,11 +114,6 @@ public: _max_samples_per_packet = num_samps; } - //! Get a scoped lock object for this instance - boost::mutex::scoped_lock get_scoped_lock(void){ - return boost::mutex::scoped_lock(_mutex); - } - //! Set the scale factor used in float conversion void set_scale_factor(const double scale_factor){ _scale_factor = scale_factor; @@ -136,8 +130,6 @@ public: const uhd::tx_metadata_t &metadata, double timeout ){ - boost::mutex::scoped_lock lock(_mutex); - //translate the metadata to vrt if packet info vrt::if_packet_info_t if_packet_info; if_packet_info.has_sid = false; @@ -200,7 +192,6 @@ public: private: - boost::mutex _mutex; vrt_packer_type _vrt_packer; size_t _header_offset_words32; double _tick_rate, _samp_rate; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index de325ea5d..7d4fe2ec7 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -138,10 +139,6 @@ struct usrp1_impl::io_impl{ zero_copy_if::sptr data_transport; - //state management for the vrt packet handler code - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; - //wrapper around the actual send buffer interface //all of this to ensure only aligned lengths are committed //NOTE: you must commit before getting a new buffer @@ -219,13 +216,6 @@ void usrp1_impl::io_impl::flush_send_buff(void){ * Initialize internals within this file **********************************************************************/ void usrp1_impl::io_init(void){ - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); @@ -234,18 +224,6 @@ void usrp1_impl::io_init(void){ &usrp1_impl::vandal_conquest_loop, this )); - //init some handler stuff - _io_impl->recv_handler.set_tick_rate(_master_clock_rate); - _io_impl->recv_handler.set_vrt_unpacker(&usrp1_bs_vrt_unpacker); - _io_impl->recv_handler.set_xport_chan_get_buff(0, boost::bind( - &uhd::transport::zero_copy_if::get_recv_buff, _io_impl->data_transport, _1 - )); - _io_impl->send_handler.set_tick_rate(_master_clock_rate); - _io_impl->send_handler.set_vrt_packer(&usrp1_bs_vrt_packer); - _io_impl->send_handler.set_xport_chan_get_buff(0, boost::bind( - &usrp1_impl::io_impl::get_send_buff, _io_impl.get(), _1 - )); - //init as disabled, then call the real function (uses restore) this->enable_rx(false); this->enable_tx(false); @@ -324,18 +302,108 @@ void usrp1_impl::vandal_conquest_loop(void){ } } +/*********************************************************************** + * RX streamer wrapper that talks to soft time control + **********************************************************************/ +class usrp1_recv_packet_streamer : public sph::recv_packet_handler, public rx_streamer{ +public: + usrp1_recv_packet_streamer(const size_t max_num_samps, soft_time_ctrl::sptr stc){ + _max_num_samps = max_num_samps; + _stc = stc; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t recv( + const rx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + uhd::rx_metadata_t &metadata, + double timeout + ){ + //interleave a "soft" inline message into the receive stream: + if (_stc->get_inline_queue().pop_with_haste(metadata)) return 0; + + size_t num_samps_recvd = sph::recv_packet_handler::recv( + buffs, nsamps_per_buff, metadata, timeout + ); + + return _stc->recv_post(metadata, num_samps_recvd); + } + +private: + size_t _max_num_samps; + soft_time_ctrl::sptr _stc; +}; + +/*********************************************************************** + * TX streamer wrapper that talks to soft time control + **********************************************************************/ +class usrp1_send_packet_streamer : public sph::send_packet_handler, public tx_streamer{ +public: + usrp1_send_packet_streamer(const size_t max_num_samps, soft_time_ctrl::sptr stc, boost::function tx_enb_fcn){ + _max_num_samps = max_num_samps; + this->set_max_samples_per_packet(_max_num_samps); + _stc = stc; + _tx_enb_fcn = tx_enb_fcn; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t send( + const tx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + const uhd::tx_metadata_t &metadata, + double timeout + ){ + if (_stc->send_pre(metadata, timeout)) return 0; + + _tx_enb_fcn(true); //always enable (it will do the right thing) + size_t num_samps_sent = sph::send_packet_handler::send( + buffs, nsamps_per_buff, metadata, timeout + ); + + //handle eob flag (commit the buffer, //disable the DACs) + //check num samps sent to avoid flush on incomplete/timeout + if (metadata.end_of_burst and num_samps_sent == nsamps_per_buff){ + async_metadata_t metadata; + metadata.channel = 0; + metadata.has_time_spec = true; + metadata.time_spec = _stc->get_time(); + metadata.event_code = async_metadata_t::EVENT_CODE_BURST_ACK; + _stc->get_async_queue().push_with_pop_on_full(metadata); + _tx_enb_fcn(false); + } + + return num_samps_sent; + } + +private: + size_t _max_num_samps; + soft_time_ctrl::sptr _stc; + boost::function _tx_enb_fcn; +}; + /*********************************************************************** * Properties callback methods below **********************************************************************/ void usrp1_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock lock = _io_impl->recv_handler.get_scoped_lock(); //sanity checking validate_subdev_spec(_tree, spec, "rx"); _rx_subdev_spec = spec; //shadow - //_io_impl->recv_handler.resize(spec.size()); //always 1 - _io_impl->recv_handler.set_converter(_rx_otw_type, spec.size()); //set the mux and set the number of rx channels std::vector mapping; @@ -351,14 +419,11 @@ void usrp1_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ } void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock lock = _io_impl->send_handler.get_scoped_lock(); //sanity checking validate_subdev_spec(_tree, spec, "tx"); _tx_subdev_spec = spec; //shadow - //_io_impl->send_handler.resize(spec.size()); //always 1 - _io_impl->send_handler.set_converter(_tx_otw_type, spec.size()); //set the mux and set the number of tx channels std::vector mapping; @@ -371,13 +436,9 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ bool s = this->disable_tx(); _iface->poke32(FR_TX_MUX, calc_tx_mux(mapping)); this->restore_tx(s); - - //if the spec changes size, so does the max samples per packet... - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); } double usrp1_impl::update_rx_samp_rate(const double samp_rate){ - boost::mutex::scoped_lock lock = _io_impl->recv_handler.get_scoped_lock(); const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 @@ -387,12 +448,17 @@ double usrp1_impl::update_rx_samp_rate(const double samp_rate){ _iface->poke32(FR_DECIM_RATE, rate/2 - 1); this->restore_rx(s); - _io_impl->recv_handler.set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } + return _master_clock_rate / rate; } double usrp1_impl::update_tx_samp_rate(const double samp_rate){ - boost::mutex::scoped_lock lock = _io_impl->send_handler.get_scoped_lock(); const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 @@ -402,10 +468,26 @@ double usrp1_impl::update_tx_samp_rate(const double samp_rate){ _iface->poke32(FR_INTERP_RATE, rate/2 - 1); this->restore_tx(s); - _io_impl->send_handler.set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } + return _master_clock_rate / rate; } +void usrp1_impl::update_rates(void){ + const fs_path mb_path = "/mboards/0"; + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ + _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").update(); + } +} + double usrp1_impl::update_rx_dsp_freq(const size_t dspno, const double freq_){ //correct for outside of rate (wrap around) @@ -443,67 +525,82 @@ bool usrp1_impl::recv_async_msg( } /*********************************************************************** - * Data send + helper functions + * Receive streamer **********************************************************************/ -size_t usrp1_impl::get_max_send_samps_per_packet(void) const { - return (_data_transport->get_send_frame_size() - alignment_padding) - / _tx_otw_type.get_sample_size() - / _tx_subdev_spec.size() - ; -} +rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size + const size_t bpp = _data_transport->get_recv_frame_size()/channels.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 my_streamer = + boost::make_shared(spp, _soft_time_ctrl); + + //init some streamer stuff + my_streamer->set_tick_rate(_master_clock_rate); + my_streamer->set_vrt_unpacker(&usrp1_bs_vrt_unpacker); + my_streamer->set_xport_chan_get_buff(0, boost::bind( + &uhd::transport::zero_copy_if::get_recv_buff, _io_impl->data_transport, _1 + )); -size_t usrp1_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 -){ - if (_soft_time_ctrl->send_pre(metadata, timeout)) return 0; + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_le"; + id.num_inputs = channels.size(); + id.output_markup = args.cpu_format; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); - this->tx_stream_on_off(true); //always enable (it will do the right thing) - size_t num_samps_sent = _io_impl->send_handler.send( - buffs, nsamps_per_buff, - metadata, io_type, - send_mode, timeout - ); + //save as weak ptr for update access + _rx_streamer = my_streamer; - //handle eob flag (commit the buffer, /*disable the DACs*/) - //check num samps sent to avoid flush on incomplete/timeout - if (metadata.end_of_burst and num_samps_sent == nsamps_per_buff){ - async_metadata_t metadata; - metadata.channel = 0; - metadata.has_time_spec = true; - metadata.time_spec = _soft_time_ctrl->get_time(); - metadata.event_code = async_metadata_t::EVENT_CODE_BURST_ACK; - _soft_time_ctrl->get_async_queue().push_with_pop_on_full(metadata); - this->tx_stream_on_off(false); - } + //sets all tick and samp rates on this streamer + this->update_rates(); - return num_samps_sent; + return my_streamer; } /*********************************************************************** - * Data recv + helper functions + * Transmit streamer **********************************************************************/ -size_t usrp1_impl::get_max_recv_samps_per_packet(void) const { - return _data_transport->get_recv_frame_size() - / _rx_otw_type.get_sample_size() - / _rx_subdev_spec.size() - ; -} +tx_streamer::sptr usrp1_impl::get_tx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size + const size_t bpp = _data_transport->get_send_frame_size()/channels.size(); + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::function tx_fcn = boost::bind(&usrp1_impl::tx_stream_on_off, this, _1); + boost::shared_ptr my_streamer = + boost::make_shared(spp, _soft_time_ctrl, tx_fcn); + + //init some streamer stuff + my_streamer->set_tick_rate(_master_clock_rate); + my_streamer->set_vrt_packer(&usrp1_bs_vrt_packer); + my_streamer->set_xport_chan_get_buff(0, boost::bind( + &usrp1_impl::io_impl::get_send_buff, _io_impl.get(), _1 + )); -size_t usrp1_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 -){ - //interleave a "soft" inline message into the receive stream: - if (_soft_time_ctrl->get_inline_queue().pop_with_haste(metadata)) return 0; + //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 = channels.size(); + id.args = args.args; + my_streamer->set_converter(id); - size_t num_samps_recvd = _io_impl->recv_handler.recv( - buffs, nsamps_per_buff, - metadata, io_type, - recv_mode, timeout - ); + //save as weak ptr for update access + _tx_streamer = my_streamer; + + //sets all tick and samp rates on this streamer + this->update_rates(); - return _soft_time_ctrl->recv_post(metadata, num_samps_recvd); + return my_streamer; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index fe4541d38..d169c4823 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -281,6 +281,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); @@ -301,6 +302,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); _tree->create(tx_dsp_path / "rate/value") + .set(1e6) .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); @@ -382,14 +384,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // do some post-init tasks //////////////////////////////////////////////////////////////////// - //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(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } - + this->update_rates(); if (_tree->list(mb_path / "rx_dsps").size() > 0) _tree->access(mb_path / "rx_subdev_spec").set(_rx_subdev_spec); if (_tree->list(mb_path / "tx_dsps").size() > 0) diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 68ce31a54..7776ea8d6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,21 +55,8 @@ public: ~usrp1_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_streamer(const uhd::streamer_args &args); + uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -94,6 +81,10 @@ private: double _master_clock_rate; //clock rate shadow + //weak pointers to streamers for update purposes + boost::weak_ptr _rx_streamer; + boost::weak_ptr _tx_streamer; + void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void set_db_eeprom(const std::string &, const std::string &, const uhd::usrp::dboard_eeprom_t &); double update_rx_codec_gain(const std::string &, const double); //sets A and B at once @@ -101,6 +92,7 @@ private: void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); double update_rx_samp_rate(const double); double update_tx_samp_rate(const double); + void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); @@ -119,8 +111,7 @@ private: void tx_stream_on_off(bool); void handle_overrun(size_t); - //otw types - uhd::otw_type_t _rx_otw_type, _tx_otw_type; + //channel mapping shadows uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //capabilities diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 44217c36c..f271d480a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -272,14 +272,12 @@ void usrp2_impl::update_tick_rate(const double rate){ boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[i].lock()); if (my_streamer.get() == NULL) continue; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); my_streamer->set_tick_rate(rate); } for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++){ boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[i].lock()); if (my_streamer.get() == NULL) continue; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); my_streamer->set_tick_rate(rate); } } @@ -290,8 +288,6 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); - my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); my_streamer->set_scale_factor(adj/32767.); @@ -302,8 +298,6 @@ void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, co boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); - my_streamer->set_samp_rate(rate); } -- cgit v1.2.3 From fac15db5d77c5196badb4a06f2f5fec34eb57337 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 09:25:54 -0700 Subject: uhd: renamed some of the stream types and functions --- host/examples/benchmark_rate.cpp | 8 +- host/examples/latency_test.cpp | 6 +- host/examples/rx_ascii_art_dft.cpp | 4 +- host/examples/rx_multi_samples.cpp | 4 +- host/examples/rx_samples_to_file.cpp | 4 +- host/examples/rx_samples_to_udp.cpp | 4 +- host/examples/rx_timed_samples.cpp | 4 +- host/examples/test_messages.cpp | 6 +- host/examples/tx_bursts.cpp | 4 +- host/examples/tx_samples_from_file.cpp | 4 +- host/examples/tx_timed_samples.cpp | 4 +- host/examples/tx_waveforms.cpp | 4 +- host/include/uhd/CMakeLists.txt | 2 +- host/include/uhd/device.hpp | 6 +- host/include/uhd/device_deprecated.ipp | 16 +- host/include/uhd/stream.hpp | 189 +++++++++++++++++++++++ host/include/uhd/streamer.hpp | 189 ----------------------- host/include/uhd/usrp/multi_usrp.hpp | 8 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- host/lib/usrp/usrp2/io_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 24 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 host/include/uhd/stream.hpp delete mode 100644 host/include/uhd/streamer.hpp (limited to 'host/lib/usrp') diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp index 7862bd44b..fce184514 100644 --- a/host/examples/benchmark_rate.cpp +++ b/host/examples/benchmark_rate.cpp @@ -44,8 +44,8 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //print pre-test summary std::cout << boost::format( @@ -98,8 +98,8 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //print pre-test summary std::cout << boost::format( diff --git a/host/examples/latency_test.cpp b/host/examples/latency_test.cpp index b995b0433..518d2383a 100644 --- a/host/examples/latency_test.cpp +++ b/host/examples/latency_test.cpp @@ -84,9 +84,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::vector > buffer(nsamps); //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //initialize result counts int time_error = 0; diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp index 14b83fb65..2e5bbba9d 100644 --- a/host/examples/rx_ascii_art_dft.cpp +++ b/host/examples/rx_ascii_art_dft.cpp @@ -148,8 +148,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //allocate recv buffer and metatdata uhd::rx_metadata_t md; diff --git a/host/examples/rx_multi_samples.cpp b/host/examples/rx_multi_samples.cpp index 56aed60af..7561f1285 100644 --- a/host/examples/rx_multi_samples.cpp +++ b/host/examples/rx_multi_samples.cpp @@ -113,10 +113,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a receive streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); //complex floats + uhd::stream_args_t stream_args("fc32"); //complex floats for (size_t chan = 0; chan < usrp->get_rx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 58bd158a5..605439748 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -39,8 +39,8 @@ template void recv_to_file( size_t samps_per_buff ){ //create a receive streamer - uhd::streamer_args stream_args(cpu_format); - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t md; std::vector buff(samps_per_buff); diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index 3db436ad5..cf7fd493a 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -131,8 +131,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 6389375d9..0851593cd 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -71,8 +71,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp index 668f25ef3..f24a172d1 100644 --- a/host/examples/test_messages.cpp +++ b/host/examples/test_messages.cpp @@ -302,9 +302,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //------------------------------------------------------------------ // begin messages test diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp index 98853ce20..f5ae18a9f 100644 --- a/host/examples/tx_bursts.cpp +++ b/host/examples/tx_bursts.cpp @@ -94,8 +94,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send const size_t spb = tx_stream->get_max_num_samps(); diff --git a/host/examples/tx_samples_from_file.cpp b/host/examples/tx_samples_from_file.cpp index 09939183b..964c6cea8 100644 --- a/host/examples/tx_samples_from_file.cpp +++ b/host/examples/tx_samples_from_file.cpp @@ -34,8 +34,8 @@ template void send_from_file( size_t samps_per_buff ){ //create a transmit streamer - uhd::streamer_args stream_args(cpu_format); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); uhd::tx_metadata_t md; md.start_of_burst = false; diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 3daf1974a..3b8cc75d4 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -74,8 +74,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send std::vector > buff(tx_stream->get_max_num_samps(), std::complex(ampl, ampl)); diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 9aa3ec71f..1eb6c2f1e 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -204,10 +204,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); + uhd::stream_args_t stream_args("fc32"); for (size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel std::vector > buff(spb); diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 6b277654d..2b0c6ec14 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -30,7 +30,7 @@ INSTALL(FILES exception.hpp property_tree.ipp property_tree.hpp - streamer.hpp + stream.hpp version.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index c96139858..89c6332da 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_DEVICE_HPP #include -#include +#include #include #include #include @@ -77,10 +77,10 @@ public: static sptr make(const device_addr_t &hint, size_t which = 0); //! Make a new receive streamer from the streamer arguments - virtual rx_streamer::sptr get_rx_streamer(const streamer_args &args) = 0; + virtual rx_streamer::sptr get_rx_stream(const stream_args_t &args) = 0; //! Make a new transmit streamer from the streamer arguments - virtual tx_streamer::sptr get_tx_streamer(const streamer_args &args) = 0; + virtual tx_streamer::sptr get_tx_stream(const stream_args_t &args) = 0; /*! * Receive and asynchronous message from the device. diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index 7afaaca2d..8e61c389f 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -80,12 +80,12 @@ size_t send( if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ _send_tid = io_type.tid; _tx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : @@ -135,12 +135,12 @@ size_t recv( if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ _recv_tid = io_type.tid; _rx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : @@ -154,10 +154,10 @@ size_t recv( */ size_t get_max_send_samps_per_packet(void){ if (_tx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); _send_tid = io_type_t::COMPLEX_FLOAT32; } return _tx_streamer->get_max_num_samps(); @@ -169,10 +169,10 @@ size_t get_max_send_samps_per_packet(void){ */ size_t get_max_recv_samps_per_packet(void){ if (_rx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); _recv_tid = io_type_t::COMPLEX_FLOAT32; } return _rx_streamer->get_max_num_samps(); diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp new file mode 100644 index 000000000..583dfd1e4 --- /dev/null +++ b/host/include/uhd/stream.hpp @@ -0,0 +1,189 @@ +// +// Copyright 2011 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 . +// + +#ifndef INCLUDED_UHD_STREAM_HPP +#define INCLUDED_UHD_STREAM_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ + +/*! + * A struct of parameters to construct a streamer. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. + */ +struct UHD_API stream_args_t{ + + //! Convenience constructor for streamer args + stream_args_t( + const std::string &cpu = "fc32", + const std::string &otw = "sc16" + ){ + cpu_format = cpu; + otw_format = otw; + } + + /*! + * The CPU format is a string that describes the format of host memory. + * Common CPU formats are: + * - fc32 - complex + * - fc64 - complex + * - sc16 - complex + * - sc8 - complex + * - f32 - float + * - f64 - double + * - s16 - int16_t + * - s8 - int8_t + */ + std::string cpu_format; + + /*! + * The OTW format is a string that describes the format over-the-wire. + * Common OTW format are: + * - sc16 - Q16 I16 + * - sc8 - Q8_1 I8_1 Q8_0 I8_0 + * - s16 - R16_1 R16_0 + * - s8 - R8_3 R8_2 R8_1 R8_0 + */ + std::string otw_format; + + /*! + * The args parameter is currently unused. Leave it blank. + * The intention is that a user with a custom DSP design + * may want to pass args and do something special with it. + */ + std::string args; + + /*! + * The channels is a list of channel numbers. + * Leave this blank to default to channel 0. + * Set channels for a multi-channel application. + * Channel mapping depends on the front-end selection. + */ + std::vector channels; +}; + +/*! + * The RX streamer is the host interface to receiving samples. + * It represents the layer between the samples on the host + * and samples inside the device's receive DSP processing. + */ +class UHD_API rx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector buffs_type; + + /*! + * Receive buffers containing samples described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. + * + * This is a blocking call and will not return until the number + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of writable memory to fill with samples + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const buffs_type &buffs, + const size_t nsamps_per_buff, + rx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +/*! + * The TX streamer is the host interface to transmitting samples. + * It represents the layer between the samples on the host + * and samples inside the device's transmit DSP processing. + */ +class UHD_API tx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector buffs_type; + + /*! + * Send buffers containing samples described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more items than the maximum per packet, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * + * This is a blocking call and will not return until the number + * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of read-only memory containing samples + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const buffs_type &buffs, + const size_t nsamps_per_buff, + const tx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_STREAM_HPP */ diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp deleted file mode 100644 index c9c6fef89..000000000 --- a/host/include/uhd/streamer.hpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// Copyright 2011 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 . -// - -#ifndef INCLUDED_UHD_STREAMER_HPP -#define INCLUDED_UHD_STREAMER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace uhd{ - -/*! - * A struct of parameters to construct a streamer. - * - * Note: - * Not all combinations of CPU and OTW format have conversion support. - * You may however write and register your own conversion routines. - */ -struct UHD_API streamer_args{ - - //! Convenience constructor for streamer args - streamer_args( - const std::string &cpu = "fc32", - const std::string &otw = "sc16" - ){ - cpu_format = cpu; - otw_format = otw; - } - - /*! - * The CPU format is a string that describes the format of host memory. - * Common CPU formats are: - * - fc32 - complex - * - fc64 - complex - * - sc16 - complex - * - sc8 - complex - * - f32 - float - * - f64 - double - * - s16 - int16_t - * - s8 - int8_t - */ - std::string cpu_format; - - /*! - * The OTW format is a string that describes the format over-the-wire. - * Common OTW format are: - * - sc16 - Q16 I16 - * - sc8 - Q8_1 I8_1 Q8_0 I8_0 - * - s16 - R16_1 R16_0 - * - s8 - R8_3 R8_2 R8_1 R8_0 - */ - std::string otw_format; - - /*! - * The args parameter is currently unused. Leave it blank. - * The intention is that a user with a custom DSP design - * may want to pass args and do something special with it. - */ - std::string args; - - /*! - * The channels is a list of channel numbers. - * Leave this blank to default to channel 0. - * Set channels for a multi-channel application. - * Channel mapping depends on the front-end selection. - */ - std::vector channels; -}; - -/*! - * The RX streamer is the host interface to receiving samples. - * It represents the layer between the samples on the host - * and samples inside the device's receive DSP processing. - */ -class UHD_API rx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of recv buffers - typedef ref_vector buffs_type; - - /*! - * Receive buffers containing samples described by the metadata. - * - * Receive handles fragmentation as follows: - * If the buffer has insufficient space to hold all samples - * that were received in a single packet over-the-wire, - * then the buffer will be completely filled and the implementation - * will hold a pointer into the remaining portion of the packet. - * Subsequent calls will load from the remainder of the packet, - * and will flag the metadata to show that this is a fragment. - * The next call to receive, after the remainder becomes exahausted, - * will perform an over-the-wire receive as usual. - * See the rx metadata fragment flags and offset fields for details. - * - * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of writable memory to fill with samples - * \param nsamps_per_buff the size of each buffer in number of samples - * \param metadata data to fill describing the buffer - * \param timeout the timeout in seconds to wait for a packet - * \return the number of samples received or 0 on error - */ - virtual size_t recv( - const buffs_type &buffs, - const size_t nsamps_per_buff, - rx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -/*! - * The TX streamer is the host interface to transmitting samples. - * It represents the layer between the samples on the host - * and samples inside the device's transmit DSP processing. - */ -class UHD_API tx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of send buffers - typedef ref_vector buffs_type; - - /*! - * Send buffers containing samples described by the metadata. - * - * Send handles fragmentation as follows: - * If the buffer has more items than the maximum per packet, - * the send method will fragment the samples across several packets. - * Send will respect the burst flags when fragmenting to ensure - * that start of burst can only be set on the first fragment and - * that end of burst can only be set on the final fragment. - * - * This is a blocking call and will not return until the number - * of samples returned have been read out of each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of read-only memory containing samples - * \param nsamps_per_buff the number of samples to send, per buffer - * \param metadata data describing the buffer's contents - * \param timeout the timeout in seconds to wait on a packet - * \return the number of samples sent - */ - virtual size_t send( - const buffs_type &buffs, - const size_t nsamps_per_buff, - const tx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -} //namespace uhd - -#endif /* INCLUDED_UHD_STREAMER_HPP */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 303af7ef9..72386204f 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -109,13 +109,13 @@ public: virtual device::sptr get_device(void) = 0; //! Convenience method to get a RX streamer - rx_streamer::sptr get_rx_streamer(const streamer_args &args){ - return this->get_device()->get_rx_streamer(args); + rx_streamer::sptr get_rx_stream(const stream_args_t &args){ + return this->get_device()->get_rx_stream(args); } //! Convenience method to get a TX streamer - tx_streamer::sptr get_tx_streamer(const streamer_args &args){ - return this->get_device()->get_tx_streamer(args); + tx_streamer::sptr get_tx_stream(const stream_args_t &args){ + return this->get_device()->get_tx_stream(args); } /******************************************************************* diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index f4dbc5531..de7b4b34c 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 079fea11e..42bac5e21 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7d4fe2ec7..22c2db6ae 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -527,7 +527,7 @@ bool usrp1_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -567,7 +567,7 @@ rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp1_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 7776ea8d6..c777307ee 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,8 +55,8 @@ public: ~usrp1_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + 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: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f271d480a..d37be403b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -366,7 +366,7 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -426,7 +426,7 @@ rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index a67c704c8..31a390af7 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -72,8 +72,8 @@ public: ~usrp2_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + 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: -- cgit v1.2.3 From de17ef4614c3c14212f239e3c735bfde3f47a68f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 13:38:29 -0700 Subject: usrp1: multi channel receive working --- host/lib/convert/convert_impl.cpp | 2 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 5c9e77e93..280957c2a 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -124,7 +124,7 @@ size_t convert::get_bytes_per_item(const std::string &markup){ return get_bytes_per_item(markup.substr(0, pos)); } - throw uhd::key_error("Cannot find an item size " + markup); + throw uhd::key_error("Cannot find an item size:\n" + markup); } UHD_STATIC_BLOCK(convert_register_item_sizes){ diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index de7b4b34c..83c8988e8 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -123,7 +123,7 @@ public: //! Set the conversion routine for all channels void set_converter(const uhd::convert::id_type &id){ - _io_buffs.resize(id.num_inputs); + _io_buffs.resize(id.num_outputs); _converter = uhd::convert::get_converter(id); _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_markup); _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_markup); diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 42bac5e21..1ac178ad2 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -99,7 +99,7 @@ public: //! Set the conversion routine for all channels void set_converter(const uhd::convert::id_type &id){ - _io_buffs.resize(id.num_outputs); + _io_buffs.resize(id.num_inputs); _converter = uhd::convert::get_converter(id); _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_markup); _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_markup); diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 22c2db6ae..03263ed26 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -549,9 +549,9 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.otw_format + "_item32_le"; - id.num_inputs = channels.size(); + id.num_inputs = 1; id.output_markup = args.cpu_format; - id.num_outputs = 1; + id.num_outputs = channels.size(); id.args = args.args; my_streamer->set_converter(id); @@ -590,9 +590,9 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.cpu_format; - id.num_inputs = 1; + id.num_inputs = channels.size(); id.output_markup = args.otw_format + "_item32_le"; - id.num_outputs = channels.size(); + id.num_outputs = 1; id.args = args.args; my_streamer->set_converter(id); -- cgit v1.2.3 From 4c4f0810ef06be18e989b6933ff236ff97c13dd0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 18:41:59 -0700 Subject: usrp1: type conversions and 8-bit work --- host/lib/convert/convert_common.hpp | 12 ++-- host/lib/convert/gen_convert_general.py | 102 ++++++++++++++++++++++++++------ host/lib/usrp/usrp1/io_impl.cpp | 69 ++++++++++++++------- host/lib/usrp/usrp1/usrp1_calc_mux.hpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- 6 files changed, 143 insertions(+), 52 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 8c8cc88b0..612fa312b 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -86,19 +86,19 @@ static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ /*********************************************************************** * Convert complex float buffer to items32 (no swap) **********************************************************************/ -static UHD_INLINE item32_t fc32_to_item32(fc32_t num, float scale_factor){ - boost::uint16_t real = boost::int16_t(num.real()*scale_factor); - boost::uint16_t imag = boost::int16_t(num.imag()*scale_factor); +static UHD_INLINE item32_t fc32_to_item32(fc32_t num, double scale_factor){ + boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor)); + boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** * Convert items32 buffer to complex float **********************************************************************/ -static UHD_INLINE fc32_t item32_to_fc32(item32_t item, float scale_factor){ +static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ return fc32_t( - float(boost::int16_t(item >> 16)*scale_factor), - float(boost::int16_t(item >> 0)*scale_factor) + float(boost::int16_t(item >> 16)*float(scale_factor)), + float(boost::int16_t(item >> 0)*float(scale_factor)) ); } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 0d68a4dd3..a5c4d4cb7 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -28,13 +28,13 @@ TMPL_HEADER = """ using namespace uhd::convert; """ -TMPL_CONV_TO_FROM_ITEM32_1 = """ +TMPL_CONV_GEN2_COMPLEX = """ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], float(scale_factor))); + output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], scale_factor)); } } @@ -43,33 +43,83 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), float(scale_factor)); + output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), scale_factor); } } """ -TMPL_CONV_TO_FROM_ITEM32_X = """ -DECLARE_CONVERTER($(cpu_type), $(width), sc16_item32_$(end), 1, PRIORITY_GENERAL){ + +TMPL_CONV_USRP1_COMPLEX = """ +DECLARE_CONVERTER($(cpu_type), $(width), sc16_item16_usrp1, 1, PRIORITY_GENERAL){ #for $w in range($width) const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); #end for - item32_t *output = reinterpret_cast(outputs[0]); + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output[j++] = $(to_wire)($(cpu_type)_to_item32(input$(w)[i], float(scale_factor))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].real()$(do_scale))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].imag()$(do_scale))); #end for } } -DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), $(width), PRIORITY_GENERAL){ - const item32_t *input = reinterpret_cast(inputs[0]); +DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); #end for + if (scale_factor == 0){} //avoids unused warning + for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output$(w)[i] = item32_to_$(cpu_type)($(to_host)(input[j++]), float(scale_factor)); + output$(w)[i] = $(cpu_type)_t( + boost::int16_t($(to_host)(input[j+0]))$(do_scale), + boost::int16_t($(to_host)(input[j+1]))$(do_scale) + ); + j += 2; + #end for + } +} + +DECLARE_CONVERTER($(cpu_type), $(width), sc8_item16_usrp1, 1, PRIORITY_GENERAL){ + #for $w in range($width) + const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); + #end for + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint8_t real = boost::int8_t(input$(w)[i].real()$(do_scale)); + const boost::uint8_t imag = boost::int8_t(input$(w)[i].imag()$(do_scale)); + output[j++] = $(to_wire)((boost::uint16_t(imag) << 8) | real); + } + #end for + } +} + +DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); + #for $w in range($width) + $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); + #end for + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint16_t num = $(to_host)(input[j++]); + output$(w)[i] = $(cpu_type)_t( + boost::int8_t(num)$(do_scale), + boost::int8_t(num >> 8)$(do_scale) + ); + } #end for } } @@ -83,14 +133,28 @@ if __name__ == '__main__': import sys, os file = os.path.basename(__file__) output = parse_tmpl(TMPL_HEADER, file=file) - for width in 1, 2, 3, 4: - for end, to_host, to_wire in ( - ('be', 'uhd::ntohx', 'uhd::htonx'), - ('le', 'uhd::wtohx', 'uhd::htowx'), + + #generate complex converters for all gen2 platforms + for end, to_host, to_wire in ( + ('be', 'uhd::ntohx', 'uhd::htonx'), + ('le', 'uhd::wtohx', 'uhd::htowx'), + ): + for cpu_type in 'fc64', 'fc32', 'sc16': + output += parse_tmpl( + TMPL_CONV_GEN2_COMPLEX, + end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type + ) + + #generate complex converters for usrp1 format + for width in 1, 2, 4: + for cpu_type, do_scale in ( + ('fc64', '*scale_factor'), + ('fc32', '*float(scale_factor)'), + ('sc16', ''), ): - for cpu_type in 'fc64', 'fc32', 'sc16': - output += parse_tmpl( - TMPL_CONV_TO_FROM_ITEM32_1 if width == 1 else TMPL_CONV_TO_FROM_ITEM32_X, - width=width, end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type - ) + output += parse_tmpl( + TMPL_CONV_USRP1_COMPLEX, + width=width, to_host='uhd::wtohx', to_wire='uhd::htowx', + cpu_type=cpu_type, do_scale=do_scale + ) open(sys.argv[1], 'w').write(output) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 03263ed26..7f20a8608 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -438,41 +438,45 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } -double usrp1_impl::update_rx_samp_rate(const double samp_rate){ +double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 + boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 16e6)), 256 ); - bool s = this->disable_rx(); - _iface->poke32(FR_DECIM_RATE, rate/2 - 1); - this->restore_rx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_rx(); + _iface->poke32(FR_DECIM_RATE, rate/2 - 1); + this->restore_rx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_rx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; } -double usrp1_impl::update_tx_samp_rate(const double samp_rate){ +double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 ); - bool s = this->disable_tx(); - _iface->poke32(FR_INTERP_RATE, rate/2 - 1); - this->restore_tx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_tx(); + _iface->poke32(FR_INTERP_RATE, rate/2 - 1); + this->restore_tx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_tx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; @@ -528,6 +532,25 @@ bool usrp1_impl::recv_async_msg( * Receive streamer **********************************************************************/ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ + if (args.otw_format == "sc16"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (0 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (16 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + ); + } + else if (args.otw_format == "sc8"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (8 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (8 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + | bmFR_RX_FORMAT_BYPASS_HB //needed for 16Msps + ); + } + else{ + throw uhd::value_error("USRP1 RX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -548,7 +571,7 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_markup = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; id.output_markup = args.cpu_format; id.num_outputs = channels.size(); @@ -568,6 +591,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ * Transmit streamer **********************************************************************/ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -591,7 +618,7 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ uhd::convert::id_type id; id.input_markup = args.cpu_format; id.num_inputs = channels.size(); - id.output_markup = args.otw_format + "_item32_le"; + id.output_markup = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; id.args = args.args; my_streamer->set_converter(id); diff --git a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp index 31c190db0..d86a7a809 100644 --- a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp +++ b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp @@ -37,7 +37,7 @@ typedef std::pair mapping_pair_t; * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_rx_mux_pair(int adc_for_i, int adc_for_q){ - return (adc_for_i << 2) | (adc_for_q << 0); //shift reversal here + return (adc_for_i << 0) | (adc_for_q << 2); } /*! @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux(const std::vector &mapping){ * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_tx_mux_pair(int chn_for_i, int chn_for_q){ - return (chn_for_i << 4) | (chn_for_q << 0); //shift reversal here + return (chn_for_i << 0) | (chn_for_q << 4); } /*! diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index d169c4823..93a301c02 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -282,7 +282,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") @@ -303,7 +303,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); _tree->create(tx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index c777307ee..cfdcbbcc1 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -90,8 +90,8 @@ private: double update_rx_codec_gain(const std::string &, const double); //sets A and B at once void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); - double update_rx_samp_rate(const double); - double update_tx_samp_rate(const double); + double update_rx_samp_rate(size_t dspno, const double); + double update_tx_samp_rate(size_t dspno, const double); void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); -- cgit v1.2.3 From 65fb4d225204b4ee2b7c73fc0ec393cfff9d6149 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 Oct 2011 10:47:56 -0700 Subject: usrp1: various tweaks related to streaming --- host/lib/convert/gen_convert_general.py | 19 ------------------- host/lib/usrp/usrp1/io_impl.cpp | 18 ++++++++++-------- host/lib/usrp/usrp1/soft_time_ctrl.cpp | 7 +++---- host/lib/usrp/usrp1/soft_time_ctrl.hpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 -- 5 files changed, 14 insertions(+), 34 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index a5c4d4cb7..0cd4155fa 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -84,25 +84,6 @@ DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL) } } -DECLARE_CONVERTER($(cpu_type), $(width), sc8_item16_usrp1, 1, PRIORITY_GENERAL){ - #for $w in range($width) - const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); - #end for - boost::uint16_t *output = reinterpret_cast(outputs[0]); - - if (scale_factor == 0){} //avoids unused warning - - for (size_t i = 0, j = 0; i < nsamps; i++){ - #for $w in range($width) - { - const boost::uint8_t real = boost::int8_t(input$(w)[i].real()$(do_scale)); - const boost::uint8_t imag = boost::int8_t(input$(w)[i].imag()$(do_scale)); - output[j++] = $(to_wire)((boost::uint16_t(imag) << 8) | real); - } - #end for - } -} - DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ const boost::uint16_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7f20a8608..835c78ecc 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -22,6 +22,7 @@ #include "../../transport/super_send_packet_handler.hpp" #include "usrp1_calc_mux.hpp" #include "fpga_regs_standard.h" +#include "fpga_regs_common.h" #include "usrp_commands.h" #include "usrp1_impl.hpp" #include @@ -367,7 +368,7 @@ public: const uhd::tx_metadata_t &metadata, double timeout ){ - if (_stc->send_pre(metadata, timeout)) return 0; + _stc->send_pre(metadata, timeout); _tx_enb_fcn(true); //always enable (it will do the right thing) size_t num_samps_sent = sph::send_packet_handler::send( @@ -440,13 +441,14 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ + const size_t div = 2; const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 16e6)), 256 - ); + boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_rx(); - _iface->poke32(FR_DECIM_RATE, rate/2 - 1); + _iface->poke32(FR_RX_SAMPLE_RATE_DIV, div - 1); + _iface->poke32(FR_DECIM_RATE, rate/div - 1); this->restore_rx(s); //update the streamer if created @@ -462,13 +464,14 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ + const size_t div = 2; const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 - ); + boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); - _iface->poke32(FR_INTERP_RATE, rate/2 - 1); + _iface->poke32(FR_TX_SAMPLE_RATE_DIV, div - 1); + _iface->poke32(FR_INTERP_RATE, rate/div - 1); this->restore_tx(s); //update the streamer if created @@ -544,7 +547,6 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ | (8 << bmFR_RX_FORMAT_SHIFT_SHIFT) | (8 << bmFR_RX_FORMAT_WIDTH_SHIFT) | bmFR_RX_FORMAT_WANT_Q - | bmFR_RX_FORMAT_BYPASS_HB //needed for 16Msps ); } else{ diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp index 78481c3ff..b8af8af06 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp @@ -131,8 +131,8 @@ public: /******************************************************************* * Transmit control ******************************************************************/ - bool send_pre(const tx_metadata_t &md, double &timeout){ - if (not md.has_time_spec) return false; + void send_pre(const tx_metadata_t &md, double &timeout){ + if (not md.has_time_spec) return; boost::mutex::scoped_lock lock(_update_mutex); @@ -146,12 +146,11 @@ public: metadata.time_spec = this->time_now(); metadata.event_code = async_metadata_t::EVENT_CODE_TIME_ERROR; _async_msg_queue.push_with_pop_on_full(metadata); - return true; + return; } timeout -= (time_at - time_now()).get_real_secs(); sleep_until_time(lock, time_at); - return false; } /******************************************************************* diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.hpp b/host/lib/usrp/usrp1/soft_time_ctrl.hpp index e91aaf6a2..b92b51252 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.hpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.hpp @@ -57,7 +57,7 @@ public: virtual size_t recv_post(rx_metadata_t &md, const size_t nsamps) = 0; //! Call before the internal send function - virtual bool send_pre(const tx_metadata_t &md, double &timeout) = 0; + virtual void send_pre(const tx_metadata_t &md, double &timeout) = 0; //! Issue a stream command to receive virtual void issue_stream_cmd(const stream_cmd_t &cmd) = 0; diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 93a301c02..108fdc9ac 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -187,8 +187,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // Normal mode with no loopback or Rx counting _iface->poke32(FR_MODE, 0x00000000); _iface->poke32(FR_DEBUG_EN, 0x00000000); - _iface->poke32(FR_RX_SAMPLE_RATE_DIV, 0x00000001); //divide by 2 - _iface->poke32(FR_TX_SAMPLE_RATE_DIV, 0x00000001); //divide by 2 _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f); // Reset offset correction registers -- cgit v1.2.3 From 861e66848f05001fcaca4fe91dbf67cd186649dc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 Oct 2011 17:30:42 -0700 Subject: usrp2: work on alternative OTW formats --- host/lib/convert/convert_common.hpp | 66 +++++++++++++++++++++++------ host/lib/convert/convert_fc32_with_sse2.cpp | 16 +++---- host/lib/convert/convert_fc64_with_sse2.cpp | 8 ++-- host/lib/convert/gen_convert_general.py | 32 +++++++++++++- host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++- host/lib/usrp/cores/rx_dsp_core_200.hpp | 1 + host/lib/usrp/usrp1/io_impl.cpp | 4 ++ host/lib/usrp/usrp2/io_impl.cpp | 7 ++- 8 files changed, 126 insertions(+), 29 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 612fa312b..56b718292 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -65,18 +65,18 @@ typedef boost::int8_t s8_t; typedef boost::uint32_t item32_t; /*********************************************************************** - * Convert complex short buffer to items32 + * Convert complex short buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t sc16_to_item32(sc16_t num, double){ +static UHD_INLINE item32_t sc16_to_item32_sc16(sc16_t num, double){ boost::uint16_t real = num.real(); boost::uint16_t imag = num.imag(); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex short + * Convert items32 sc16 buffer to complex short **********************************************************************/ -static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ +static UHD_INLINE sc16_t item32_sc16_to_sc16(item32_t item, double){ return sc16_t( boost::int16_t(item >> 16), boost::int16_t(item >> 0) @@ -84,18 +84,18 @@ static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ } /*********************************************************************** - * Convert complex float buffer to items32 (no swap) + * Convert complex float buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t fc32_to_item32(fc32_t num, double scale_factor){ +static UHD_INLINE item32_t fc32_to_item32_sc16(fc32_t num, double scale_factor){ boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor)); boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex float + * Convert items32 sc16 buffer to complex float **********************************************************************/ -static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ +static UHD_INLINE fc32_t item32_sc16_to_fc32(item32_t item, double scale_factor){ return fc32_t( float(boost::int16_t(item >> 16)*float(scale_factor)), float(boost::int16_t(item >> 0)*float(scale_factor)) @@ -103,22 +103,64 @@ static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ } /*********************************************************************** - * Convert complex double buffer to items32 (no swap) + * Convert complex double buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t fc64_to_item32(fc64_t num, double scale_factor){ +static UHD_INLINE item32_t fc64_to_item32_sc16(fc64_t num, double scale_factor){ boost::uint16_t real = boost::int16_t(num.real()*scale_factor); boost::uint16_t imag = boost::int16_t(num.imag()*scale_factor); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex double + * Convert items32 sc16 buffer to complex double **********************************************************************/ -static UHD_INLINE fc64_t item32_to_fc64(item32_t item, double scale_factor){ +static UHD_INLINE fc64_t item32_sc16_to_fc64(item32_t item, double scale_factor){ return fc64_t( float(boost::int16_t(item >> 16)*scale_factor), float(boost::int16_t(item >> 0)*scale_factor) ); } +/*********************************************************************** + * Convert items32 sc8 buffer to complex short + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_sc16(item32_t item, sc16_t &out0, sc16_t &out1, double){ + out0 = sc16_t( + boost::int8_t(item >> 8), + boost::int8_t(item >> 0) + ); + out1 = sc16_t( + boost::int8_t(item >> 24), + boost::int8_t(item >> 16) + ); +} + +/*********************************************************************** + * Convert items32 sc8 buffer to complex float + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_fc32(item32_t item, fc32_t &out0, fc32_t &out1, double scale_factor){ + out0 = fc32_t( + float(boost::int8_t(item >> 8)*float(scale_factor)), + float(boost::int8_t(item >> 0)*float(scale_factor)) + ); + out1 = fc32_t( + float(boost::int8_t(item >> 24)*float(scale_factor)), + float(boost::int8_t(item >> 16)*float(scale_factor)) + ); +} + +/*********************************************************************** + * Convert items32 sc8 buffer to complex double + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_fc64(item32_t item, fc64_t &out0, fc64_t &out1, double scale_factor){ + out0 = fc64_t( + float(boost::int8_t(item >> 8)*scale_factor), + float(boost::int8_t(item >> 0)*scale_factor) + ); + out1 = fc64_t( + float(boost::int8_t(item >> 24)*scale_factor), + float(boost::int8_t(item >> 16)*scale_factor) + ); +} + #endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */ diff --git a/host/lib/convert/convert_fc32_with_sse2.cpp b/host/lib/convert/convert_fc32_with_sse2.cpp index 34c85db80..b8d1aa8cc 100644 --- a/host/lib/convert/convert_fc32_with_sse2.cpp +++ b/host/lib/convert/convert_fc32_with_sse2.cpp @@ -51,7 +51,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(input) & 0xf){ case 0x8: - output[i] = fc32_to_item32(input[i], float(scale_factor)); i++; + output[i] = fc32_to_item32_sc16(input[i], float(scale_factor)); i++; case 0x0: convert_fc32_1_to_item32_1_nswap_guts(_) break; @@ -60,7 +60,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = fc32_to_item32(input[i], float(scale_factor)); + output[i] = fc32_to_item32_sc16(input[i], float(scale_factor)); } } @@ -93,7 +93,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(input) & 0xf){ case 0x8: - output[i] = uhd::byteswap(fc32_to_item32(input[i], float(scale_factor))); i++; + output[i] = uhd::byteswap(fc32_to_item32_sc16(input[i], float(scale_factor))); i++; case 0x0: convert_fc32_1_to_item32_1_bswap_guts(_) break; @@ -102,7 +102,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = uhd::byteswap(fc32_to_item32(input[i], float(scale_factor))); + output[i] = uhd::byteswap(fc32_to_item32_sc16(input[i], float(scale_factor))); } } @@ -138,7 +138,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(output) & 0xf){ case 0x8: - output[i] = item32_to_fc32(input[i], float(scale_factor)); i++; + output[i] = item32_sc16_to_fc32(input[i], float(scale_factor)); i++; case 0x0: convert_item32_1_to_fc32_1_nswap_guts(_) break; @@ -147,7 +147,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc32(input[i], float(scale_factor)); + output[i] = item32_sc16_to_fc32(input[i], float(scale_factor)); } } @@ -182,7 +182,7 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(output) & 0xf){ case 0x8: - output[i] = item32_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); i++; + output[i] = item32_sc16_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); i++; case 0x0: convert_item32_1_to_fc32_1_bswap_guts(_) break; @@ -191,6 +191,6 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); + output[i] = item32_sc16_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); } } diff --git a/host/lib/convert/convert_fc64_with_sse2.cpp b/host/lib/convert/convert_fc64_with_sse2.cpp index 2093cf476..a4f2df2e7 100644 --- a/host/lib/convert/convert_fc64_with_sse2.cpp +++ b/host/lib/convert/convert_fc64_with_sse2.cpp @@ -64,7 +64,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = fc64_to_item32(input[i], scale_factor); + output[i] = fc64_to_item32_sc16(input[i], scale_factor); } } @@ -110,7 +110,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = uhd::byteswap(fc64_to_item32(input[i], scale_factor)); + output[i] = uhd::byteswap(fc64_to_item32_sc16(input[i], scale_factor)); } } @@ -159,7 +159,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc64(input[i], scale_factor); + output[i] = item32_sc16_to_fc64(input[i], scale_factor); } } @@ -207,6 +207,6 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc64(uhd::byteswap(input[i]), scale_factor); + output[i] = item32_sc16_to_fc64(uhd::byteswap(input[i]), scale_factor); } } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 0cd4155fa..43e1f9967 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -34,7 +34,7 @@ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], scale_factor)); + output[i] = $(to_wire)($(cpu_type)_to_item32_sc16(input[i], scale_factor)); } } @@ -43,7 +43,35 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), scale_factor); + output[i] = item32_sc16_to_$(cpu_type)($(to_host)(input[i]), scale_factor); + } +} + +DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ + const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); + $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); + $(cpu_type)_t dummy; + + const bool head_case = ((size_t(inputs[0]) & 0x3) != 0); + const bool tail_case = ((nsamps & 0x1) == 0)? head_case : not head_case; + const size_t num_pairs = (head_case? nsamps-1 : nsamps)/2; + size_t i = 0, j = 0; + + //special head case, probably from a partial recv + if (head_case){ + const item32_t item0 = $(to_host)(input[i++]); + item32_sc8_to_$(cpu_type)(item0, dummy, output[j++], scale_factor); + } + + for (; i < num_pairs; i++, j+=2){ + const item32_t item_i = $(to_host)(input[i]); + item32_sc8_to_$(cpu_type)(item_i, output[j], output[j+1], scale_factor); + } + + //special tail case, finished on an odd number + if (tail_case){ + const item32_t item_i = $(to_host)(input[i]); + item32_sc8_to_$(cpu_type)(item_i, output[j], dummy, scale_factor); } } """ diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index d562c64db..023216a09 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -42,6 +42,7 @@ #define REG_RX_CTRL_VRT_TLR _ctrl_base + 24 #define REG_RX_CTRL_NSAMPS_PP _ctrl_base + 28 #define REG_RX_CTRL_NCHANNELS _ctrl_base + 32 +#define REG_RX_CTRL_FORMAT _ctrl_base + 36 template T ceil_log2(T num){ return std::ceil(std::log(num)/std::log(T(2))); @@ -162,7 +163,7 @@ public: } double get_scaling_adjustment(void){ - return _scaling_adjustment; + return _scaling_adjustment/_fxpt_scale_adj; } double set_freq(const double freq_){ @@ -192,12 +193,28 @@ public: if (_continuous_streaming) issue_stream_command(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); } + void set_format(const std::string &format, const unsigned scale){ + unsigned format_word = 0; + if (format == "sc16"){ + format_word = 0; + _fxpt_scale_adj = 32767.; + } + else if (format == "sc8"){ + format_word = (1 << 18); + _fxpt_scale_adj = 32767./scale; + } + else throw uhd::value_error("USRP RX cannot handle requested wire format: " + format); + + const unsigned scale_word = scale & 0x3ffff; //18 bits; + _iface->poke32(REG_RX_CTRL_FORMAT, format_word | scale_word); + } + private: wb_iface::sptr _iface; const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; bool _continuous_streaming; - double _scaling_adjustment; + double _scaling_adjustment, _fxpt_scale_adj; }; rx_dsp_core_200::sptr rx_dsp_core_200::make(wb_iface::sptr iface, const size_t dsp_base, const size_t ctrl_base, const boost::uint32_t sid, const bool lingering_packet){ diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index 391cc8441..ddd6f2abf 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -56,6 +56,7 @@ public: virtual void handle_overflow(void) = 0; + virtual void set_format(const std::string &format, const unsigned scale) = 0; }; #endif /* INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 835c78ecc..eaa6d02b4 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -564,6 +564,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp, _soft_time_ctrl); + //special scale factor change for sc8 + if (args.otw_format == "sc8") + my_streamer->set_scale_factor(1.0/127); + //init some streamer stuff my_streamer->set_tick_rate(_master_clock_rate); my_streamer->set_vrt_unpacker(&usrp1_bs_vrt_unpacker); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d37be403b..f917a35db 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -290,7 +290,7 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); - my_streamer->set_scale_factor(adj/32767.); + my_streamer->set_scale_factor(adj); } void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ @@ -404,6 +404,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ if (chan < num_chan_so_far){ const size_t dsp = num_chan_so_far - chan - 1; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, 0x400); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 )); @@ -427,6 +428,10 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ * Transmit streamer **********************************************************************/ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; -- cgit v1.2.3 From 0946176f513dd58407869e3b019207ff3eef24f5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 Oct 2011 20:55:01 -0700 Subject: usrp1: got the 16Msps working (needed non hb-filter image) --- host/include/uhd/stream.hpp | 4 ++-- host/lib/usrp/usrp1/io_impl.cpp | 40 +++++++++++++++++++++++++------------- host/lib/usrp/usrp1/usrp1_impl.cpp | 6 ------ host/lib/usrp/usrp2/io_impl.cpp | 32 +++++++++++++++++------------- 4 files changed, 48 insertions(+), 34 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 583dfd1e4..7a3151276 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -39,8 +39,8 @@ struct UHD_API stream_args_t{ //! Convenience constructor for streamer args stream_args_t( - const std::string &cpu = "fc32", - const std::string &otw = "sc16" + const std::string &cpu = "", + const std::string &otw = "" ){ cpu_format = cpu; otw_format = otw; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index eaa6d02b4..c199e4178 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -441,10 +441,16 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ - const size_t div = 2; + const size_t div = this->has_rx_halfband()? 2 : 1; const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); + if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << + "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" + "The usrp1_fpga_4rx.rbf file is a special FPGA image without RX half-band filters.\n" + "To load this image, set the device address key/value pair: fpga=usrp1_fpga_4rx.rbf\n" + << std::endl; + if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_rx(); _iface->poke32(FR_RX_SAMPLE_RATE_DIV, div - 1); @@ -464,7 +470,7 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ - const size_t div = 2; + const size_t div = this->has_tx_halfband()? 2 : 1; const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); @@ -534,7 +540,13 @@ bool usrp1_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ +rx_streamer::sptr usrp1_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(1, 0) : args.channels; + if (args.otw_format == "sc16"){ _iface->poke32(FR_RX_FORMAT, 0 | (0 << bmFR_RX_FORMAT_SHIFT_SHIFT) @@ -553,11 +565,8 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ throw uhd::value_error("USRP1 RX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; - //calculate packet size - const size_t bpp = _data_transport->get_recv_frame_size()/channels.size(); + const size_t bpp = _data_transport->get_recv_frame_size()/args.channels.size(); const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); //make the new streamer given the samples per packet @@ -580,7 +589,7 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ id.input_markup = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; id.output_markup = args.cpu_format; - id.num_outputs = channels.size(); + id.num_outputs = args.channels.size(); id.args = args.args; my_streamer->set_converter(id); @@ -596,16 +605,21 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ +tx_streamer::sptr usrp1_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(1, 0) : args.channels; + if (args.otw_format != "sc16"){ throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + _iface->poke32(FR_TX_FORMAT, bmFR_TX_FORMAT_16_IQ); //calculate packet size - const size_t bpp = _data_transport->get_send_frame_size()/channels.size(); + const size_t bpp = _data_transport->get_send_frame_size()/args.channels.size(); const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); //make the new streamer given the samples per packet @@ -623,7 +637,7 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.cpu_format; - id.num_inputs = channels.size(); + id.num_inputs = args.channels.size(); id.output_markup = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; id.args = args.args; diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 108fdc9ac..db652b033 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -195,12 +195,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _iface->poke32(FR_ADC_OFFSET_2, 0x00000000); _iface->poke32(FR_ADC_OFFSET_3, 0x00000000); - // Set default for RX format to 16-bit I&Q and no half-band filter bypass - _iface->poke32(FR_RX_FORMAT, 0x00000300); - - // Set default for TX format to 16-bit I&Q - _iface->poke32(FR_TX_FORMAT, 0x00000000); - UHD_LOG << "USRP1 Capabilities" << std::endl << " number of duc's: " << get_num_ddcs() << std::endl diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f917a35db..f1d0aee2a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -366,9 +366,12 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; +rx_streamer::sptr usrp2_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(1, 0) : args.channels; //calculate packet size static const size_t hdr_size = 0 @@ -383,7 +386,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp); //init some streamer stuff - my_streamer->resize(channels.size()); + my_streamer->resize(args.channels.size()); my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_be); //set the converter @@ -396,8 +399,8 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ my_streamer->set_converter(id); //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ - const size_t chan = channels[chan_i]; + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].rx_chan_occ; @@ -427,14 +430,17 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ +tx_streamer::sptr usrp2_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(1, 0) : args.channels; + if (args.otw_format != "sc16"){ throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -448,7 +454,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp); //init some streamer stuff - my_streamer->resize(channels.size()); + my_streamer->resize(args.channels.size()); my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); //set the converter @@ -461,8 +467,8 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ my_streamer->set_converter(id); //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ - const size_t chan = channels[chan_i]; + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; size_t abs = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ -- cgit v1.2.3 From fce49fd66f577b92482af6ad516944befa31b861 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 10:29:33 -0700 Subject: uhd: added one packet mode to rx streamer --- host/include/uhd/stream.hpp | 10 +++++-- host/lib/transport/super_recv_packet_handler.hpp | 14 +++++----- host/lib/transport/super_send_packet_handler.hpp | 6 ++--- host/lib/usrp/usrp1/io_impl.cpp | 18 +++++++++---- host/tests/sph_recv_test.cpp | 33 ++++++++++++------------ 5 files changed, 47 insertions(+), 34 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 7a3151276..c86463184 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -123,17 +123,23 @@ public: * Under a timeout condition, the number of samples returned * may be less than the number of samples specified. * + * The one_packet option allows the user to guarantee that + * the call will return after a single packet has been processed. + * This may be useful to maintain packet boundaries in some cases. + * * \param buffs a vector of writable memory to fill with samples * \param nsamps_per_buff the size of each buffer in number of samples * \param metadata data to fill describing the buffer * \param timeout the timeout in seconds to wait for a packet + * \param one_packet return after the first packet is received * \return the number of samples received or 0 on error */ virtual size_t recv( const buffs_type &buffs, const size_t nsamps_per_buff, rx_metadata_t &metadata, - double timeout = 0.1 + const double timeout = 0.1, + const bool one_packet = false ) = 0; }; @@ -180,7 +186,7 @@ public: const buffs_type &buffs, const size_t nsamps_per_buff, const tx_metadata_t &metadata, - double timeout = 0.1 + const double timeout = 0.1 ) = 0; }; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 83c8988e8..6762a8a00 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -148,7 +148,8 @@ public: const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ //handle metadata queued from a previous receive if (_queue_error_for_next_call){ @@ -163,9 +164,7 @@ public: buffs, nsamps_per_buff, metadata, timeout ); - #ifdef SRPH_TEST_MODE_ONE_PACKET - return accum_num_samps; - #endif + if (one_packet) return accum_num_samps; //first recv had an error code set, return immediately if (metadata.error_code != rx_metadata_t::ERROR_CODE_NONE) return accum_num_samps; @@ -493,7 +492,7 @@ private: const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout, + const double timeout, const size_t buffer_offset_bytes = 0 ){ //get the next buffer if the current one has expired @@ -571,9 +570,10 @@ public: const rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ - return recv_packet_handler::recv(buffs, nsamps_per_buff, metadata, timeout); + return recv_packet_handler::recv(buffs, nsamps_per_buff, metadata, timeout, one_packet); } private: diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 1ac178ad2..5b5ee2981 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -128,7 +128,7 @@ public: const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout ){ //translate the metadata to vrt if packet info vrt::if_packet_info_t if_packet_info; @@ -215,7 +215,7 @@ private: const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, vrt::if_packet_info_t &if_packet_info, - double timeout, + const double timeout, const size_t buffer_offset_bytes = 0 ){ //load the rest of the if_packet_info in here @@ -269,7 +269,7 @@ public: const tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout ){ return send_packet_handler::send(buffs, nsamps_per_buff, metadata, timeout); } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index c199e4178..a0fdfc6bf 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -325,13 +325,14 @@ public: const rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ //interleave a "soft" inline message into the receive stream: if (_stc->get_inline_queue().pop_with_haste(metadata)) return 0; size_t num_samps_recvd = sph::recv_packet_handler::recv( - buffs, nsamps_per_buff, metadata, timeout + buffs, nsamps_per_buff, metadata, timeout, one_packet ); return _stc->recv_post(metadata, num_samps_recvd); @@ -366,8 +367,9 @@ public: const tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout_ ){ + double timeout = timeout_; //rw copy _stc->send_pre(metadata, timeout); _tx_enb_fcn(true); //always enable (it will do the right thing) @@ -545,7 +547,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + args.channels.clear(); //NOTE: we have no choice about the channel mapping + for (size_t ch = 0; ch < _rx_subdev_spec.size(); ch++){ + args.channels.push_back(ch); + } if (args.otw_format == "sc16"){ _iface->poke32(FR_RX_FORMAT, 0 @@ -610,7 +615,10 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + args.channels.clear(); //NOTE: we have no choice about the channel mapping + for (size_t ch = 0; ch < _tx_subdev_spec.size(); ch++){ + args.channels.push_back(ch); + } if (args.otw_format != "sc16"){ throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 3ca123ef2..6fab2ad5f 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -16,7 +16,6 @@ // #include -#define SRPH_TEST_MODE_ONE_PACKET #include "../lib/transport/super_recv_packet_handler.hpp" #include #include @@ -155,7 +154,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -169,7 +168,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -228,7 +227,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -250,7 +249,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -319,7 +318,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -329,7 +328,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ num_accum_samps += num_samps_ret; if (i == NUM_PKTS_TO_TEST/2){ handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); std::cout << "metadata.error_code " << metadata.error_code << std::endl; BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); @@ -342,7 +341,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -410,7 +409,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -424,7 +423,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -496,7 +495,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -518,7 +517,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -589,7 +588,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -606,7 +605,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -674,7 +673,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(metadata.has_time_spec); @@ -685,7 +684,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ if (not metadata.more_fragments) continue; num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -700,7 +699,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } -- cgit v1.2.3 From 5538048873f140f3ac2bbab12dc5b0729f68f1a5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 12:12:25 -0700 Subject: usrp1: support variable clock rate through API --- host/docs/usrp1.rst | 6 ++++++ host/lib/usrp/usrp1/dboard_iface.cpp | 26 +++++++++++++------------- host/lib/usrp/usrp1/io_impl.cpp | 9 +++++++++ host/lib/usrp/usrp1/usrp1_impl.cpp | 36 ++++++++++++++++++++++++++++-------- host/lib/usrp/usrp1/usrp1_impl.hpp | 5 ++++- 5 files changed, 60 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 8b274a2b3..597b5b17f 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -84,3 +84,9 @@ Run the following commands to record the setting into the EEPROM: cd /share/uhd/utils ./usrp_burn_mb_eeprom --args= --key=mcr --val= + +The user may override the clock rate specified in the EEPROM by using a device address: +Example: +:: + + uhd_usrp_probe --args="mcr=52e6" diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 449ec64fe..34bbe1893 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -39,7 +39,7 @@ public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ): _dboard_slot(dboard_slot), @@ -49,10 +49,8 @@ public: _iface = iface; _codec = codec; - //init the clock rate shadows - this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front()); - this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front()); - + _dbsrx_classic_div = 1; + //yes this is evil but it's necessary for TVRX to work on USRP1 if(_rx_dboard_id == tvrx_id) _codec->bypass_adc_buffers(false); //else _codec->bypass_adc_buffers(false); //don't think this is necessary @@ -103,9 +101,9 @@ public: private: usrp1_iface::sptr _iface; usrp1_codec_ctrl::sptr _codec; - uhd::dict _clock_rates; + unsigned _dbsrx_classic_div; const usrp1_impl::dboard_slot_t _dboard_slot; - const double _master_clock_rate; + const double &_master_clock_rate; const dboard_id_t _rx_dboard_id; }; @@ -115,7 +113,7 @@ private: dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ){ return dboard_iface::sptr(new usrp1_dboard_iface( @@ -137,17 +135,16 @@ static const dboard_id_t dbsrx_classic_id(0x0002); void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate) { assert_has(this->get_clock_rates(unit), rate, "dboard clock rate"); - _clock_rates[unit] = rate; if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ - size_t divider = size_t(_master_clock_rate/rate); + _dbsrx_classic_div = size_t(_master_clock_rate/rate); switch(_dboard_slot){ case usrp1_impl::DBOARD_SLOT_A: - _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_A_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; case usrp1_impl::DBOARD_SLOT_B: - _iface->poke32(FR_RX_B_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_B_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; } } @@ -168,7 +165,10 @@ std::vector usrp1_dboard_iface::get_clock_rates(unit_t unit) double usrp1_dboard_iface::get_clock_rate(unit_t unit) { - return _clock_rates[unit]; + if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ + return _master_clock_rate/_dbsrx_classic_div; + } + return _master_clock_rate; } void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index a0fdfc6bf..f46f4741b 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -441,6 +441,14 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } + +void usrp1_impl::update_tick_rate(const double rate){ + //updating this variable should: + //update dboard iface -> it has a reference + //update dsp freq bounds -> publisher + _master_clock_rate = rate; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; @@ -495,6 +503,7 @@ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ void usrp1_impl::update_rates(void){ const fs_path mb_path = "/mboards/0"; + this->update_tick_rate(_master_clock_rate); BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index db652b033..5788c536f 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -225,14 +225,25 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // create clock control objects //////////////////////////////////////////////////////////////////// _master_clock_rate = 64e6; - try{ - if (not mb_eeprom["mcr"].empty()) + if (device_addr.has_key("mcr")){ + try{ + _master_clock_rate = boost::lexical_cast(device_addr["mcr"]); + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from device address: " << e.what() << std::endl; + } + } + else if (not mb_eeprom["mcr"].empty()){ + try{ _master_clock_rate = boost::lexical_cast(mb_eeprom["mcr"]); - }catch(const std::exception &e){ - UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } } UHD_MSG(status) << boost::format("Using FPGA clock rate of %fMHz...") % (_master_clock_rate/1e6) << std::endl; - _tree->create(mb_path / "tick_rate").set(_master_clock_rate); + _tree->create(mb_path / "tick_rate") + .subscribe(boost::bind(&usrp1_impl::update_tick_rate, this, _1)); //////////////////////////////////////////////////////////////////// // create codec control objects @@ -278,7 +289,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") - .set(meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2)); + .publish(boost::bind(&usrp1_impl::get_rx_dsp_freq_range, this)); _tree->create(rx_dsp_path / "stream_cmd"); if (dspno == 0){ //only subscribe the callback for dspno 0 since it will stream all dsps @@ -298,8 +309,8 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); - _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: - .set(meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875)); + _tree->create(tx_dsp_path / "freq/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_freq_range, this)); } //////////////////////////////////////////////////////////////////// @@ -443,3 +454,12 @@ double usrp1_impl::update_rx_codec_gain(const std::string &db, const double gain _dbc[db].codec->set_rx_pga_gain(gain, 'B'); return _dbc[db].codec->get_rx_pga_gain('A'); } + +uhd::meta_range_t usrp1_impl::get_rx_dsp_freq_range(void){ + return meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2); +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ + //magic scalar comes from codec control: + return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index cfdcbbcc1..6f427c31e 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -95,12 +95,15 @@ private: void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); + void update_tick_rate(const double rate); + uhd::meta_range_t get_rx_dsp_freq_range(void); + uhd::meta_range_t get_tx_dsp_freq_range(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, usrp1_codec_ctrl::sptr, dboard_slot_t, - const double, + const double &, const uhd::usrp::dboard_id_t & ); -- cgit v1.2.3 From ba0323c616e032ebde12073521c754d93c65f821 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 14:54:02 -0700 Subject: b100: performed streamer API update to b100 impl --- host/lib/usrp/b100/b100_impl.cpp | 18 ++-- host/lib/usrp/b100/b100_impl.hpp | 23 ++-- host/lib/usrp/b100/io_impl.cpp | 222 ++++++++++++++++++++++++--------------- 3 files changed, 151 insertions(+), 112 deletions(-) (limited to 'host/lib/usrp') 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(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(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -317,8 +318,9 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); _tree->create(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(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1)); _tree->create(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(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(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } + _tree->access(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(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); _tree->access(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 #include #include -#include #include #include #include @@ -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 > _rx_streamers; + std::vector > _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 #include #include +#include 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_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(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(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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(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(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 my_streamer = boost::make_shared(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(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 my_streamer = boost::make_shared(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; } -- cgit v1.2.3 From 9fc513c961775c9682123394fe5d42ef914bbbd6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 17:46:44 -0700 Subject: e100: performed streamer API update to e100 impl --- host/lib/usrp/b100/b100_impl.hpp | 1 + host/lib/usrp/e100/e100_impl.cpp | 18 ++- host/lib/usrp/e100/e100_impl.hpp | 18 +-- host/lib/usrp/e100/io_impl.cpp | 241 +++++++++++++++++++++++---------------- 4 files changed, 162 insertions(+), 116 deletions(-) (limited to 'host/lib/usrp') 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 #include #include +#include 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(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(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -291,8 +292,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); _tree->create(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(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1)); _tree->create(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(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(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } + _tree->access(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(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); _tree->access(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 #include #include -#include -#include #include #include #include +#include #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 > _rx_streamers; + std::vector > _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 //open, close #include #include +#include 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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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 my_streamer = + boost::dynamic_pointer_cast(_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(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(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(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(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(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 my_streamer = boost::make_shared(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(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 my_streamer = boost::make_shared(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; } -- cgit v1.2.3 From c885da11389ee275f9c5206b9f8a2155a5393a8a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 Oct 2011 00:39:04 -0700 Subject: uhd: renamed convert markup to format removed convert args added simd level got orc and neon updated --- host/include/uhd/convert.hpp | 16 ++++----- host/lib/convert/convert_common.hpp | 16 ++++----- host/lib/convert/convert_fc32_with_sse2.cpp | 8 ++--- host/lib/convert/convert_fc64_with_sse2.cpp | 8 ++--- host/lib/convert/convert_impl.cpp | 37 +++++++++----------- host/lib/convert/convert_with_neon.cpp | 8 ++--- host/lib/convert/convert_with_orc.cpp | 12 +++---- host/lib/transport/super_recv_packet_handler.hpp | 4 +-- host/lib/transport/super_send_packet_handler.hpp | 4 +-- host/lib/usrp/b100/io_impl.cpp | 10 +++--- host/lib/usrp/e100/io_impl.cpp | 10 +++--- host/lib/usrp/usrp1/io_impl.cpp | 10 +++--- host/lib/usrp/usrp2/io_impl.cpp | 10 +++--- host/tests/convert_test.cpp | 44 ++++++++++++------------ host/tests/sph_recv_test.cpp | 28 +++++++-------- host/tests/sph_send_test.cpp | 8 ++--- 16 files changed, 110 insertions(+), 123 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index a0b502ab0..c42edfdec 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -42,17 +42,17 @@ namespace uhd{ namespace convert{ enum priority_type{ PRIORITY_GENERAL = 0, PRIORITY_LIBORC = 1, - PRIORITY_CUSTOM = 2, + PRIORITY_SIMD = 2, + PRIORITY_CUSTOM = 3, PRIORITY_EMPTY = -1, }; //! Identify a conversion routine in the registry struct id_type : boost::equality_comparable{ - std::string input_markup; + std::string input_format; size_t num_inputs; - std::string output_markup; + std::string output_format; size_t num_outputs; - std::string args; std::string to_pp_string(void) const; }; @@ -80,15 +80,15 @@ namespace uhd{ namespace convert{ /*! * Register the size of a particular item. - * \param markup the item markup + * \param format the item format * \param size the size in bytes */ UHD_API void register_bytes_per_item( - const std::string &markup, const size_t size + const std::string &format, const size_t size ); - //! Convert an item markup to a size in bytes - UHD_API size_t get_bytes_per_item(const std::string &markup); + //! Convert an item format to a size in bytes + UHD_API size_t get_bytes_per_item(const std::string &format); }} //namespace diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 56b718292..34fb848c3 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -23,30 +23,28 @@ #include #include -#define _DECLARE_CONVERTER(fcn, in_mark, num_in, out_mark, num_out, prio) \ +#define _DECLARE_CONVERTER(fcn, in_form, num_in, out_form, num_out, prio) \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - const size_t nsamps, \ - const double scale_factor \ + const size_t nsamps, const double scale_factor \ ); \ UHD_STATIC_BLOCK(__register_##fcn##_##prio){ \ uhd::convert::id_type id; \ - id.input_markup = #in_mark; \ + id.input_format = #in_form; \ id.num_inputs = num_in; \ - id.output_markup = #out_mark; \ + id.output_format = #out_form; \ id.num_outputs = num_out; \ uhd::convert::register_converter(id, fcn, prio); \ } \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - const size_t nsamps, \ - const double scale_factor \ + const size_t nsamps, const double scale_factor \ ) -#define DECLARE_CONVERTER(in_mark, num_in, out_mark, num_out, prio) \ - _DECLARE_CONVERTER(__convert_##in_mark##_##num_in##_##out_mark##_##num_out, in_mark, num_in, out_mark, num_out, prio) +#define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \ + _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out, in_form, num_in, out_form, num_out, prio) /*********************************************************************** * Typedefs diff --git a/host/lib/convert/convert_fc32_with_sse2.cpp b/host/lib/convert/convert_fc32_with_sse2.cpp index b8d1aa8cc..24a939d6c 100644 --- a/host/lib/convert/convert_fc32_with_sse2.cpp +++ b/host/lib/convert/convert_fc32_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -64,7 +64,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -106,7 +106,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); @@ -151,7 +151,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_fc64_with_sse2.cpp b/host/lib/convert/convert_fc64_with_sse2.cpp index a4f2df2e7..837bb584e 100644 --- a/host/lib/convert/convert_fc64_with_sse2.cpp +++ b/host/lib/convert/convert_fc64_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -68,7 +68,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_SIMD){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -114,7 +114,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); @@ -163,7 +163,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 280957c2a..df03b44f9 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -27,29 +27,26 @@ using namespace uhd; bool convert::operator==(const convert::id_type &lhs, const convert::id_type &rhs){ - return - (lhs.input_markup == rhs.input_markup) and - (lhs.num_inputs == rhs.num_inputs) and - (lhs.output_markup == rhs.output_markup) and - (lhs.num_outputs == rhs.num_outputs) and - (lhs.args == rhs.args) + return true + and (lhs.input_format == rhs.input_format) + and (lhs.num_inputs == rhs.num_inputs) + and (lhs.output_format == rhs.output_format) + and (lhs.num_outputs == rhs.num_outputs) ; } std::string convert::id_type::to_pp_string(void) const{ return str(boost::format( "conversion ID\n" - " Input markup: %s\n" + " Input format: %s\n" " Num inputs: %d\n" - " Output markup: %s\n" + " Output format: %s\n" " Num outputs: %d\n" - " Optional args: %s\n" ) - % this->input_markup + % this->input_format % this->num_inputs - % this->output_markup + % this->output_format % this->num_outputs - % this->args ); } @@ -101,30 +98,30 @@ convert::function_type convert::get_converter(const id_type &id){ } /*********************************************************************** - * Mappings for item markup to byte size for all items we can + * Mappings for item format to byte size for all items we can **********************************************************************/ typedef uhd::dict item_size_type; UHD_SINGLETON_FCN(item_size_type, get_item_size_table); void register_bytes_per_item( - const std::string &markup, const size_t size + const std::string &format, const size_t size ){ - get_item_size_table()[markup] = size; + get_item_size_table()[format] = size; } -size_t convert::get_bytes_per_item(const std::string &markup){ - if (get_item_size_table().has_key(markup)) return get_item_size_table()[markup]; +size_t convert::get_bytes_per_item(const std::string &format){ + if (get_item_size_table().has_key(format)) return get_item_size_table()[format]; //OK. I am sorry about this. //We didnt find a match, so lets find a match for the first term. //This is partially a hack because of the way I append strings. //But as long as life is kind, we can keep this. - const size_t pos = markup.find("_"); + const size_t pos = format.find("_"); if (pos != std::string::npos){ - return get_bytes_per_item(markup.substr(0, pos)); + return get_bytes_per_item(format.substr(0, pos)); } - throw uhd::key_error("Cannot find an item size:\n" + markup); + throw uhd::key_error("Cannot find an item size:\n" + format); } UHD_STATIC_BLOCK(convert_register_item_sizes){ diff --git a/host/lib/convert/convert_with_neon.cpp b/host/lib/convert/convert_with_neon.cpp index e5f08cad9..c7ad62104 100644 --- a/host/lib/convert/convert_with_neon.cpp +++ b/host/lib/convert/convert_with_neon.cpp @@ -20,7 +20,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -37,10 +37,10 @@ DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ } for (; i < nsamps; i++) - output[i] = fc32_to_item32(input[i], float(scale_factor)); + output[i] = fc32_to_item32_sc16(input[i], scale_factor); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); @@ -57,5 +57,5 @@ DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ } for (; i < nsamps; i++) - output[i] = item32_to_fc32(input[i], float(scale_factor)); + output[i] = item32_sc16_to_fc32(input[i], scale_factor); } diff --git a/host/lib/convert/convert_with_orc.cpp b/host/lib/convert/convert_with_orc.cpp index 844c2595c..0c46bcf1e 100644 --- a/host/lib/convert/convert_with_orc.cpp +++ b/host/lib/convert/convert_with_orc.cpp @@ -29,26 +29,26 @@ extern void _convert_sc16_1_to_item32_1_nswap_orc(void *, const void *, float, i extern void _convert_item32_1_to_sc16_1_nswap_orc(void *, const void *, float, int); } -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_LIBORC){ _convert_fc32_1_to_item32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_bswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_LIBORC){ _convert_fc32_1_to_item32_1_bswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_LIBORC){ _convert_item32_1_to_fc32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_bswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_LIBORC){ _convert_item32_1_to_fc32_1_bswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_sc16_1_to_item32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16, 1, sc16_item32_le, 1, PRIORITY_LIBORC){ _convert_sc16_1_to_item32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_sc16_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_le, 1, sc16, 1, PRIORITY_LIBORC){ _convert_item32_1_to_sc16_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 6762a8a00..2310d6aea 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -125,8 +125,8 @@ public: void set_converter(const uhd::convert::id_type &id){ _io_buffs.resize(id.num_outputs); _converter = uhd::convert::get_converter(id); - _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_markup); - _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_markup); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_format); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_format); } //! Set the transport channel's overflow handler diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 5b5ee2981..779259d4f 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -101,8 +101,8 @@ public: void set_converter(const uhd::convert::id_type &id){ _io_buffs.resize(id.num_inputs); _converter = uhd::convert::get_converter(id); - _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_markup); - _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_markup); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_format); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_format); } /*! diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 82298dca6..28b19f14e 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -218,11 +218,10 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_format = args.otw_format + "_item32_le"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -276,11 +275,10 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_le"; + id.output_format = args.otw_format + "_item32_le"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 5936ee2d7..c47eb8940 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -294,11 +294,10 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_format = args.otw_format + "_item32_le"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -352,11 +351,10 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_le"; + id.output_format = args.otw_format + "_item32_le"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index f46f4741b..534d33959 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -600,11 +600,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item16_usrp1"; + id.input_format = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = args.channels.size(); - id.args = args.args; my_streamer->set_converter(id); //save as weak ptr for update access @@ -653,11 +652,10 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = args.channels.size(); - id.output_markup = args.otw_format + "_item16_usrp1"; + id.output_format = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //save as weak ptr for update access diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f1d0aee2a..660156285 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -391,11 +391,10 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_be"; + id.input_format = args.otw_format + "_item32_be"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -459,11 +458,10 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_be"; + id.output_format = args.otw_format + "_item32_be"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp index 9dabcf54e..b63ff6752 100644 --- a/host/tests/convert_test.cpp +++ b/host/tests/convert_test.cpp @@ -75,7 +75,7 @@ static void test_convert_types_sc16( //run the loopback and test convert::id_type in_id = id; convert::id_type out_id = id; - std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.input_format, out_id.output_format); std::swap(out_id.num_inputs, out_id.num_outputs); loopback(nsamps, in_id, out_id, input, output); BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); @@ -83,9 +83,9 @@ static void test_convert_types_sc16( BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){ convert::id_type id; - id.input_markup = "sc16"; + id.input_format = "sc16"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -96,9 +96,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){ BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){ convert::id_type id; - id.input_markup = "sc16"; + id.input_format = "sc16"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -126,7 +126,7 @@ static void test_convert_types_for_floats( //run the loopback and test convert::id_type in_id = id; convert::id_type out_id = id; - std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.input_format, out_id.output_format); std::swap(out_id.num_inputs, out_id.num_outputs); loopback(nsamps, in_id, out_id, input, output); for (size_t i = 0; i < nsamps; i++){ @@ -137,9 +137,9 @@ static void test_convert_types_for_floats( BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){ convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){ convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -163,9 +163,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){ convert::id_type id; - id.input_markup = "fc64"; + id.input_format = "fc64"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -176,9 +176,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ convert::id_type id; - id.input_markup = "fc64"; + id.input_format = "fc64"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -192,15 +192,15 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ convert::id_type in_id; - in_id.input_markup = "fc32"; + in_id.input_format = "fc32"; in_id.num_inputs = 1; - in_id.output_markup = "sc16_item32_le"; + in_id.output_format = "sc16_item32_le"; in_id.num_outputs = 1; convert::id_type out_id; - out_id.input_markup = "sc16_item32_le"; + out_id.input_format = "sc16_item32_le"; out_id.num_inputs = 1; - out_id.output_markup = "sc16"; + out_id.output_format = "sc16"; out_id.num_outputs = 1; const size_t nsamps = 13; @@ -233,15 +233,15 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){ convert::id_type in_id; - in_id.input_markup = "sc16"; + in_id.input_format = "sc16"; in_id.num_inputs = 1; - in_id.output_markup = "sc16_item32_le"; + in_id.output_format = "sc16_item32_le"; in_id.num_outputs = 1; convert::id_type out_id; - out_id.input_markup = "sc16_item32_le"; + out_id.input_format = "sc16_item32_le"; out_id.num_inputs = 1; - out_id.output_markup = "fc32"; + out_id.output_format = "fc32"; out_id.num_outputs = 1; const size_t nsamps = 13; diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 6fab2ad5f..85d06aa0d 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -107,9 +107,9 @@ private: BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -178,9 +178,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -259,9 +259,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -351,9 +351,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -434,9 +434,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -527,9 +527,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -615,9 +615,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; diff --git a/host/tests/sph_send_test.cpp b/host/tests/sph_send_test.cpp index 9a91008af..25a3f97ee 100644 --- a/host/tests/sph_send_test.cpp +++ b/host/tests/sph_send_test.cpp @@ -92,9 +92,9 @@ private: BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; dummy_send_xport_class dummy_send_xport("big"); @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; dummy_send_xport_class dummy_send_xport("big"); -- cgit v1.2.3 From 9369259177e5517e2b0e775804224c5467e14eab Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 Oct 2011 09:59:41 -0700 Subject: usrp: deprecated clock config, added time/clock source calls --- host/include/uhd/deprecated.hpp | 1 + host/include/uhd/types/clock_config.hpp | 5 ++- host/include/uhd/usrp/multi_usrp.hpp | 53 +++++++++++++++++++++++- host/lib/deprecated.cpp | 28 +++++++++++++ host/lib/types/CMakeLists.txt | 1 - host/lib/types/clock_config.cpp | 44 -------------------- host/lib/usrp/multi_usrp.cpp | 72 +++++++++++++++++++++++---------- 7 files changed, 136 insertions(+), 68 deletions(-) delete mode 100644 host/lib/types/clock_config.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index e4112fa66..d918836f1 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -243,3 +243,4 @@ namespace uhd{ #endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ #include //wish it was in here +#include //wish it was in here diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 24bd96d14..27b312245 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -23,10 +23,13 @@ namespace uhd{ /*! - * Clock configuration settings: + * The DEPRECATED Clock configuration settings: * The source for the 10MHz reference clock. * The source and polarity for the PPS clock. * + * Deprecated in favor of set time/clock source calls. + * Its still in this file for the sake of gr-uhd swig. + * * Use the convenience functions external() and internal(), * unless you have a special purpose and cannot use them. */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 72386204f..ee7bf8424 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -18,11 +18,13 @@ #ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP #define INCLUDED_UHD_USRP_MULTI_USRP_HPP +#define UHD_USRP_MULTI_USRP_REF_SOURCES_API + #include #include +#include #include #include -#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include namespace uhd{ namespace usrp{ @@ -235,6 +238,7 @@ public: /*! * Set the clock configuration for the usrp device. + * DEPRECATED in favor of set time and clock source calls. * This tells the usrp how to get a 10Mhz reference and PPS clock. * See the documentation for clock_config_t for more info. * \param clock_config the clock configuration to set @@ -242,6 +246,53 @@ public: */ virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard = ALL_MBOARDS) = 0; + /*! + * Set the time source for the usrp device. + * This sets the method of time synchronization, + * typically a pulse per second or an encoded time. + * Typical options for source: external, MIMO. + * \param source a string representing the time source + * \param mboard which motherboard to set the config + */ + virtual void set_time_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set time source. + * \param mboard which motherboard to get the config + * \return the string representing the time source + */ + virtual std::string get_time_source(const size_t mboard) = 0; + + /*! + * Get a list of possible time sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector get_time_sources(const size_t mboard) = 0; + + /*! + * Set the clock source for the usrp device. + * This sets the source for a 10 Mhz reference clock. + * Typical options for source: internal, external, MIMO. + * \param source a string representing the clock source + * \param mboard which motherboard to set the config + */ + virtual void set_clock_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set clock source. + * \param mboard which motherboard to get the config + * \return the string representing the clock source + */ + virtual std::string get_clock_source(const size_t mboard) = 0; + + /*! + * Get a list of possible clock sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector get_clock_sources(const size_t mboard) = 0; + /*! * Get the number of USRP motherboards in this configuration. */ diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp index dd4cc02ad..b659d1be5 100644 --- a/host/lib/deprecated.cpp +++ b/host/lib/deprecated.cpp @@ -203,3 +203,31 @@ io_type_t::io_type_t(size_t size): { /* NOP */ } + +#include + +using namespace uhd; + +clock_config_t clock_config_t::external(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_SMA; + clock_config.pps_source = clock_config_t::PPS_SMA; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + +clock_config_t clock_config_t::internal(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_INT; + clock_config.pps_source = clock_config_t::PPS_SMA; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + +clock_config_t::clock_config_t(void): + ref_source(REF_INT), + pps_source(PPS_SMA), + pps_polarity(PPS_POS) +{ + /* NOP */ +} diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index 957dfd345..2ca0faef7 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -80,7 +80,6 @@ SET_SOURCE_FILES_PROPERTIES( # This file included, use CMake directory variables ######################################################################## LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/clock_config.cpp ${CMAKE_CURRENT_SOURCE_DIR}/device_addr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mac_addr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp diff --git a/host/lib/types/clock_config.cpp b/host/lib/types/clock_config.cpp deleted file mode 100644 index c150c5cc3..000000000 --- a/host/lib/types/clock_config.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright 2011 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 - -using namespace uhd; - -clock_config_t clock_config_t::external(void){ - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_SMA; - clock_config.pps_source = clock_config_t::PPS_SMA; - clock_config.pps_polarity = clock_config_t::PPS_POS; - return clock_config; -} - -clock_config_t clock_config_t::internal(void){ - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_INT; - clock_config.pps_source = clock_config_t::PPS_SMA; - clock_config.pps_polarity = clock_config_t::PPS_POS; - return clock_config; -} - -clock_config_t::clock_config_t(void): - ref_source(REF_INT), - pps_source(PPS_SMA), - pps_polarity(PPS_POS) -{ - /* NOP */ -} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 73699dc81..ab841487f 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -359,34 +359,64 @@ public: } void set_clock_config(const clock_config_t &clock_config, size_t mboard){ + //set the reference source... + std::string clock_source; + switch(clock_config.ref_source){ + case clock_config_t::REF_INT: clock_source = "internal"; break; + case clock_config_t::PPS_SMA: clock_source = "external"; break; + case clock_config_t::PPS_MIMO: clock_source = "mimo"; break; + default: clock_source = "unknown"; + } + this->set_clock_source(clock_source, mboard); + + //set the time source + std::string time_source; + switch(clock_config.pps_source){ + case clock_config_t::PPS_INT: time_source = "internal"; break; + case clock_config_t::PPS_SMA: time_source = "external"; break; + case clock_config_t::PPS_MIMO: time_source = "mimo"; break; + default: time_source = "unknown"; + } + if (time_source == "external" and clock_config.pps_polarity == clock_config_t::PPS_NEG) time_source = "_external_"; + this->set_time_source(time_source, mboard); + } + + void set_time_source(const std::string &source, const size_t mboard){ if (mboard != ALL_MBOARDS){ - //set the reference source... - std::string clock_source; - switch(clock_config.ref_source){ - case clock_config_t::REF_INT: clock_source = "internal"; break; - case clock_config_t::PPS_SMA: clock_source = "external"; break; - case clock_config_t::PPS_MIMO: clock_source = "mimo"; break; - default: clock_source = "unknown"; - } - _tree->access(mb_root(mboard) / "clock_source" / "value").set(clock_source); - - //set the time source - std::string time_source; - switch(clock_config.pps_source){ - case clock_config_t::PPS_INT: time_source = "internal"; break; - case clock_config_t::PPS_SMA: time_source = "external"; break; - case clock_config_t::PPS_MIMO: time_source = "mimo"; break; - default: time_source = "unknown"; - } - if (clock_source == "external" and clock_config.pps_polarity == clock_config_t::PPS_NEG) time_source = "_external_"; - _tree->access(mb_root(mboard) / "time_source" / "value").set(time_source); + _tree->access(mb_root(mboard) / "time_source" / "value").set(source); return; } for (size_t m = 0; m < get_num_mboards(); m++){ - set_clock_config(clock_config, m); + return this->set_time_source(source, m); } } + std::string get_time_source(const size_t mboard){ + return _tree->access(mb_root(mboard) / "time_source" / "value").get(); + } + + std::vector get_time_sources(const size_t mboard){ + return _tree->access >(mb_root(mboard) / "time_source" / "options").get(); + } + + void set_clock_source(const std::string &source, const size_t mboard){ + if (mboard != ALL_MBOARDS){ + _tree->access(mb_root(mboard) / "clock_source" / "value").set(source); + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + return this->set_clock_source(source, m); + } + } + + std::string get_clock_source(const size_t mboard){ + return _tree->access(mb_root(mboard) / "clock_source" / "value").get(); + } + + std::vector get_clock_sources(const size_t mboard){ + return _tree->access >(mb_root(mboard) / "clock_source" / "options").get(); + } + size_t get_num_mboards(void){ return _tree->list("/mboards").size(); } -- cgit v1.2.3 From 00b6d8359de6ea616f7bd6573d7f87d635d78a79 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 Oct 2011 13:08:12 -0700 Subject: uhd: added trailer parsing for occupancy --- host/include/uhd/transport/vrt_if_packet.hpp | 1 + host/lib/convert/gen_convert_general.py | 1 + host/lib/transport/gen_vrt_if_packet.py | 51 ++++++++++++++++-------- host/lib/transport/super_recv_packet_handler.hpp | 11 ++--- host/lib/transport/super_send_packet_handler.hpp | 3 +- host/lib/usrp/cores/rx_dsp_core_200.cpp | 3 +- host/lib/usrp/cores/tx_dsp_core_200.cpp | 3 +- host/lib/usrp/usrp1/io_impl.cpp | 1 + 8 files changed, 46 insertions(+), 28 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index 51bd81bb1..1be480874 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -44,6 +44,7 @@ namespace vrt{ //size fields size_t num_payload_words32; //required in pack, derived in unpack + size_t num_payload_bytes; //required in pack, derived in unpack size_t num_header_words32; //derived in pack, derived in unpack size_t num_packet_words32; //derived in pack, required in unpack diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 9a1135b0b..be5a65130 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -48,6 +48,7 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ } DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ + if (nsamps == 0) return; //otherwise segfault const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); $(cpu_type)_t dummy; diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 5f048d8c7..245a7ddbd 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -70,6 +70,10 @@ static pred_table_type get_pred_unpack_table(void){ static const pred_table_type pred_unpack_table(get_pred_unpack_table()); +//maps trailer bits to num empty bytes +//maps num empty bytes to trailer bits +static const size_t occ_table[] = {0, 2, 1, 3}; + ######################################################################## #def gen_code($XE_MACRO, $suffix) ######################################################################## @@ -122,14 +126,6 @@ void vrt::if_hdr_pack_$(suffix)( #set $num_header_words += 1 #set $flags |= (0x1 << 20); #end if - ########## Trailer ########## - #if $pred & $tlr_p - //packet_buff[$num_header_words+if_packet_info.num_payload_words32] = $(XE_MACRO)(if_packet_info.tlr); - #set $flags |= (0x1 << 26); - #set $num_trailer_words = 1; - #else - #set $num_trailer_words = 0; - #end if ########## Burst Flags ########## #if $pred & $eob_p #set $flags |= (0x1 << 24); @@ -137,6 +133,18 @@ void vrt::if_hdr_pack_$(suffix)( #if $pred & $sob_p #set $flags |= (0x1 << 25); #end if + ########## Trailer ########## + #if $pred & $tlr_p + { + const size_t empty_bytes = if_packet_info.num_payload_words32*sizeof(boost::uint32_t) - if_packet_info.num_payload_bytes; + if_packet_info.tlr |= (0x3 << 22) | (occ_table[empty_bytes & 0x3] << 10); + } + packet_buff[$num_header_words+if_packet_info.num_payload_words32] = $(XE_MACRO)(if_packet_info.tlr); + #set $flags |= (0x1 << 26); + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if ########## Variables ########## if_packet_info.num_header_words32 = $num_header_words; if_packet_info.num_packet_words32 = $($num_header_words + $num_trailer_words) + if_packet_info.num_payload_words32; @@ -172,6 +180,8 @@ void vrt::if_hdr_unpack_$(suffix)( const pred_type pred = pred_unpack_table[pred_table_index(vrt_hdr_word)]; + size_t empty_bytes = 0; + switch(pred){ #for $pred in range(2**7) case $pred: @@ -211,15 +221,6 @@ void vrt::if_hdr_unpack_$(suffix)( #else if_packet_info.has_tsf = false; #end if - ########## Trailer ########## - #if $pred & $tlr_p - if_packet_info.has_tlr = true; - if_packet_info.tlr = $(XE_MACRO)(packet_buff[packet_words32-1]); - #set $num_trailer_words = 1; - #else - if_packet_info.has_tlr = false; - #set $num_trailer_words = 0; - #end if ########## Burst Flags ########## #if $pred & $eob_p if_packet_info.eob = true; @@ -231,12 +232,28 @@ void vrt::if_hdr_unpack_$(suffix)( #else if_packet_info.sob = false; #end if + ########## Trailer ########## + #if $pred & $tlr_p + if_packet_info.has_tlr = true; + if_packet_info.tlr = $(XE_MACRO)(packet_buff[packet_words32-1]); + #set $num_trailer_words = 1; + { + const int indicators = (if_packet_info.tlr >> 20) & (if_packet_info.tlr >> 8); + if ((indicators & (1 << 0)) != 0) if_packet_info.eob = true; + if ((indicators & (1 << 1)) != 0) if_packet_info.sob = true; + empty_bytes = occ_table[(indicators >> 2) & 0x3]; + } + #else + if_packet_info.has_tlr = false; + #set $num_trailer_words = 0; + #end if ########## Variables ########## //another failure case if (packet_words32 < $($num_header_words + $num_trailer_words)) throw uhd::value_error("bad vrt header or invalid packet length"); if_packet_info.num_header_words32 = $num_header_words; if_packet_info.num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words); + if_packet_info.num_payload_bytes = if_packet_info.num_payload_words32*sizeof(boost::uint32_t) - empty_bytes; break; #end for } diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 2310d6aea..48b0acdb9 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -327,7 +327,7 @@ private: info.alignment_time = info[index].time; info.indexes_todo.set(); info.indexes_todo.reset(index); - info.data_bytes_to_copy = info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t); + info.data_bytes_to_copy = info[index].ifpi.num_payload_bytes; } //if the sequence id matches: @@ -471,13 +471,8 @@ private: curr_info.metadata.time_spec = curr_info[0].time; curr_info.metadata.more_fragments = false; curr_info.metadata.fragment_offset = 0; - /* TODO SOB on RX not supported in hardware - static const int tlr_sob_flags = (1 << 21) | (1 << 9); //enable and indicator bits - curr_info.metadata.start_of_burst = curr_info[0].ifpi.has_tlr and (int(curr_info[0].ifpi.tlr & tlr_sob_flags) != 0); - */ - curr_info.metadata.start_of_burst = false; - static const int tlr_eob_flags = (1 << 20) | (1 << 8); //enable and indicator bits - curr_info.metadata.end_of_burst = curr_info[0].ifpi.has_tlr and (int(curr_info[0].ifpi.tlr & tlr_eob_flags) != 0); + curr_info.metadata.start_of_burst = curr_info[0].ifpi.sob; + curr_info.metadata.end_of_burst = curr_info[0].ifpi.eob; curr_info.metadata.error_code = rx_metadata_t::ERROR_CODE_NONE; } diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 779259d4f..5696b5d39 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -219,7 +219,8 @@ private: const size_t buffer_offset_bytes = 0 ){ //load the rest of the if_packet_info in here - if_packet_info.num_payload_words32 = (nsamps_per_buff*_io_buffs.size()*_bytes_per_otw_item)/sizeof(boost::uint32_t); + if_packet_info.num_payload_bytes = nsamps_per_buff*_io_buffs.size()*_bytes_per_otw_item; + if_packet_info.num_payload_words32 = (if_packet_info.num_payload_bytes + 3/*round up*/)/sizeof(boost::uint32_t); if_packet_info.packet_count = _next_packet_seq; size_t buff_index = 0; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 023216a09..b121bc849 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -130,7 +130,8 @@ public: } void set_link_rate(const double rate){ - _link_rate = rate/sizeof(boost::uint32_t); //in samps/s + //_link_rate = rate/sizeof(boost::uint32_t); //in samps/s + _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } double set_host_rate(const double rate){ diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 04e9f5da4..f37b53527 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -70,7 +70,8 @@ public: } void set_link_rate(const double rate){ - _link_rate = rate/sizeof(boost::uint32_t); //in samps/s + //_link_rate = rate/sizeof(boost::uint32_t); //in samps/s + _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } double set_host_rate(const double rate){ diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 534d33959..12950d385 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -111,6 +111,7 @@ static void usrp1_bs_vrt_unpacker( ){ if_packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_DATA; if_packet_info.num_payload_words32 = if_packet_info.num_packet_words32; + if_packet_info.num_payload_bytes = if_packet_info.num_packet_words32*sizeof(boost::uint32_t); if_packet_info.num_header_words32 = 0; if_packet_info.packet_count = 0; if_packet_info.sob = false; -- cgit v1.2.3 From ae9e89d76b2eb86a29995f04aaab1aa59ee93f04 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 16 Oct 2011 10:43:48 -0700 Subject: usrp: added get_tx/rx_rates --- host/include/uhd/usrp/multi_usrp.hpp | 16 ++++++++++++++++ host/lib/usrp/b100/b100_impl.cpp | 4 ++++ host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/rx_dsp_core_200.hpp | 2 ++ host/lib/usrp/cores/tx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/tx_dsp_core_200.hpp | 2 ++ host/lib/usrp/e100/e100_impl.cpp | 4 ++++ host/lib/usrp/multi_usrp.cpp | 8 ++++++++ host/lib/usrp/usrp1/io_impl.cpp | 27 ++++++++++++++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 8 ++++++-- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 ++ host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++++ 12 files changed, 102 insertions(+), 17 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index ee7bf8424..baa47b39e 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -18,7 +18,9 @@ #ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP #define INCLUDED_UHD_USRP_MULTI_USRP_HPP +//define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API +#define UHD_USRP_MULTI_USRP_GET_RATES_API #include #include @@ -367,6 +369,13 @@ public: */ virtual double get_rx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible RX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_rx_rates(size_t chan = 0) = 0; + /*! * Set the RX center frequency. * \param tune_request tune request instructions @@ -567,6 +576,13 @@ public: */ virtual double get_tx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible TX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_tx_rates(size_t chan = 0) = 0; + /*! * Set the TX center frequency. * \param tune_request tune request instructions diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index d1928735b..bb91d415d 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -296,6 +296,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .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(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -317,6 +319,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tx_dsp->set_link_rate(B100_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index b121bc849..6d306d507 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -134,12 +134,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t decim_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (decim_rate > 128) decim_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (decim_rate > 256) decim_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t decim_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t decim = decim_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index ddd6f2abf..89b8c1f51 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -48,6 +48,8 @@ public: virtual double set_host_rate(const double rate) = 0; + virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual double get_scaling_adjustment(void) = 0; virtual uhd::meta_range_t get_freq_range(void) = 0; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index f37b53527..1d571ea7c 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -74,12 +74,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t interp_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (interp_rate > 128) interp_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (interp_rate > 256) interp_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t interp_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t interp = interp_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp index 65f822558..e6be63557 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp @@ -40,6 +40,8 @@ public: virtual double set_host_rate(const double rate) = 0; + virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual uhd::meta_range_t get_freq_range(void) = 0; virtual double set_freq(const double freq) = 0; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index deb52b2d7..6cb404000 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -270,6 +270,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .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(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -291,6 +293,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tx_dsp->set_link_rate(E100_TX_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index ab841487f..97c5ea630 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -477,6 +477,10 @@ public: return _tree->access(rx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_rx_rates(size_t chan){ + return _tree->access(rx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); @@ -587,6 +591,10 @@ public: return _tree->access(tx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_tx_rates(size_t chan){ + return _tree->access(tx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 12950d385..31c834109 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -442,7 +442,6 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } - void usrp1_impl::update_tick_rate(const double rate){ //updating this variable should: //update dboard iface -> it has a reference @@ -450,11 +449,29 @@ void usrp1_impl::update_tick_rate(const double rate){ _master_clock_rate = rate; } +uhd::meta_range_t usrp1_impl::get_rx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_rx_halfband()? 2 : 1; + for (int rate = 256; rate >= 4; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_tx_halfband()? 2 : 1; + for (int rate = 256; rate >= 8; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); + const size_t rate = this->get_rx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" @@ -482,8 +499,8 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_tx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); + const size_t rate = this->get_tx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 5788c536f..1a61f8136 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -283,8 +283,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "rx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_rx_dsp_host_rates, this)); _tree->create(rx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); @@ -304,8 +306,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); + _tree->create(tx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_host_rates, this)); _tree->create(tx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 6f427c31e..ec313daf6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -98,6 +98,8 @@ private: void update_tick_rate(const double rate); uhd::meta_range_t get_rx_dsp_freq_range(void); uhd::meta_range_t get_tx_dsp_freq_range(void); + uhd::meta_range_t get_rx_dsp_host_rates(void); + uhd::meta_range_t get_tx_dsp_host_rates(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2d89ddaf4..24178d10c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -480,6 +480,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1)) @@ -501,6 +503,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _mbc[mb].tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) -- cgit v1.2.3 From 07ba94643ed2cfeed91542e3c1fc59cbdb39a932 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 Oct 2011 16:38:27 -0700 Subject: usrp: add api control for tx/rx dc offset control --- host/include/uhd/usrp/multi_usrp.hpp | 35 +++++++++++++++++++++++++++++++++++ host/lib/usrp/multi_usrp.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index baa47b39e..9fbc9cfe6 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -21,6 +21,7 @@ //define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API +#define UHD_USRP_MULTI_USRP_DC_OFFSET_API #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -528,6 +530,30 @@ public: */ virtual std::vector get_rx_sensor_names(size_t chan = 0) = 0; + + /*! + * Enable/disable the automatic RX DC offset correction. + * The automatic correction subtracts out the long-run average. + * + * When disabled, the averaging option operation is halted. + * Once halted, the average value will be held constant + * until the user re-enables the automatic correction + * or overrides the value by manually setting the offset. + * + * \param enb true to enable automatic DC offset correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const bool enb, size_t chan = ALL_CHANS) = 0; + + /*! + * Set a constant RX DC offset value. + * The value is complex to control both I and Q. + * Only set this when automatic correction is disabled. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -724,6 +750,15 @@ public: * \return a vector of sensor names */ virtual std::vector get_tx_sensor_names(size_t chan = 0) = 0; + + /*! + * Set a constant TX DC offset value. + * The value is complex to control both I and Q. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + }; }} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 97c5ea630..5fff989ce 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -547,6 +547,26 @@ public: return _tree->list(rx_rf_fe_root(chan) / "sensors"); } + void set_rx_dc_offset(const bool enb, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "enable").set(enb); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_dc_offset(enb, c); + } + } + + void set_rx_dc_offset(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_dc_offset(offset, c); + } + } + /******************************************************************* * TX methods ******************************************************************/ @@ -661,6 +681,16 @@ public: return _tree->list(tx_rf_fe_root(chan) / "sensors"); } + void set_tx_dc_offset(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(tx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_tx_num_channels(); c++){ + this->set_tx_dc_offset(offset, c); + } + } + private: device::sptr _dev; property_tree::sptr _tree; -- cgit v1.2.3 From f11d64579a7c1421cc2b0f04c85f0c0e82b6a74e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 Oct 2011 16:38:45 -0700 Subject: usrp1: implement rx dc offset control hooks --- host/lib/usrp/usrp1/usrp1_impl.cpp | 41 +++++++++++++++++++++++++++++++------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 ++++ 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 1a61f8136..fcc4f36ae 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include using namespace uhd; @@ -187,13 +188,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // Normal mode with no loopback or Rx counting _iface->poke32(FR_MODE, 0x00000000); _iface->poke32(FR_DEBUG_EN, 0x00000000); - _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f); - - // Reset offset correction registers - _iface->poke32(FR_ADC_OFFSET_0, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_1, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_2, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_3, 0x00000000); UHD_LOG << "USRP1 Capabilities" << std::endl @@ -277,6 +271,15 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp1_impl::update_tx_subdev_spec, this, _1)); + BOOST_FOREACH(const std::string &db, _dbc.keys()){ + _tree->create >(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&usrp1_impl::set_rx_dc_offset, this, db, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&usrp1_impl::set_enb_rx_dc_offset, this, db, _1)) + .set(true); + } + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// @@ -467,3 +470,27 @@ uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ //magic scalar comes from codec control: return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); } + +void usrp1_impl::set_enb_rx_dc_offset(const std::string &db, const bool enb){ + const size_t shift = (db == "A")? 0 : 2; + _rx_dc_offset_shadow &= ~(0x3 << shift); //clear bits + _rx_dc_offset_shadow &= ((enb)? 0x3 : 0x0) << shift; + _iface->poke32(FR_DC_OFFSET_CL_EN, _rx_dc_offset_shadow & 0xf); +} + +std::complex usrp1_impl::set_rx_dc_offset(const std::string &db, const std::complex &offset){ + const boost::int32_t i_off = boost::math::iround(offset.real() * (1ul << 31)); + const boost::int32_t q_off = boost::math::iround(offset.imag() * (1ul << 31)); + + if (db == "A"){ + _iface->poke32(FR_ADC_OFFSET_0, i_off); + _iface->poke32(FR_ADC_OFFSET_1, q_off); + } + + if (db == "B"){ + _iface->poke32(FR_ADC_OFFSET_2, i_off); + _iface->poke32(FR_ADC_OFFSET_3, q_off); + } + + return std::complex(double(i_off) * (1ul << 31), double(q_off) * (1ul << 31)); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index ec313daf6..99bb01c76 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef INCLUDED_USRP1_IMPL_HPP #define INCLUDED_USRP1_IMPL_HPP @@ -100,6 +101,9 @@ private: uhd::meta_range_t get_tx_dsp_freq_range(void); uhd::meta_range_t get_rx_dsp_host_rates(void); uhd::meta_range_t get_tx_dsp_host_rates(void); + size_t _rx_dc_offset_shadow; + void set_enb_rx_dc_offset(const std::string &db, const bool); + std::complex set_rx_dc_offset(const std::string &db, const std::complex &); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, -- cgit v1.2.3 From c63a38e1f9b383663e5bb52a1ae35b54bbc0104e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:02:43 -0700 Subject: usrp: add api call to adjust phase/mag imbalance --- host/include/uhd/usrp/multi_usrp.hpp | 20 +++++++++++++++++++- host/lib/usrp/multi_usrp.cpp | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 9fbc9cfe6..1cbe3a684 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -22,6 +22,7 @@ #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_DC_OFFSET_API +#define UHD_USRP_MULTI_USRP_CORRECTION_API #include #include @@ -530,7 +531,6 @@ public: */ virtual std::vector get_rx_sensor_names(size_t chan = 0) = 0; - /*! * Enable/disable the automatic RX DC offset correction. * The automatic correction subtracts out the long-run average. @@ -554,6 +554,15 @@ public: */ virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /*! + * Set the RX frontend IQ imbalance and gain correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction value + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -759,6 +768,15 @@ public: */ virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /*! + * Set the TX frontend IQ imbalance and gain correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction value + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + }; }} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 5fff989ce..5a6acc2c5 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -567,6 +567,16 @@ public: } } + void set_rx_correction(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(rx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_correction(offset, c); + } + } + /******************************************************************* * TX methods ******************************************************************/ @@ -691,6 +701,16 @@ public: } } + void set_tx_correction(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(tx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_tx_num_channels(); c++){ + this->set_tx_correction(offset, c); + } + } + private: device::sptr _dev; property_tree::sptr _tree; -- cgit v1.2.3 From 3d3c77983b917fefc7a3e59669a43e440ba4f688 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:03:56 -0700 Subject: usrp: update frontend cores for dc offset --- host/lib/usrp/cores/rx_frontend_core_200.cpp | 24 +++++++++++++++++++++--- host/lib/usrp/cores/rx_frontend_core_200.hpp | 4 +++- host/lib/usrp/cores/tx_frontend_core_200.cpp | 12 +++++++++--- host/lib/usrp/cores/tx_frontend_core_200.hpp | 2 +- 4 files changed, 34 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/cores/rx_frontend_core_200.cpp b/host/lib/usrp/cores/rx_frontend_core_200.cpp index 0e8220b49..bb87cb600 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.cpp @@ -24,6 +24,9 @@ #define REG_RX_FE_OFFSET_I _base + 12 //18 bits #define REG_RX_FE_OFFSET_Q _base + 16 //18 bits +#define OFFSET_FIXED (1ul << 31) +#define OFFSET_SET (1ul << 30) + static boost::uint32_t fs_to_bits(const double num, const size_t bits){ return boost::int32_t(boost::math::round(num * (1 << (bits-1)))); } @@ -41,9 +44,23 @@ public: _iface->poke32(REG_RX_FE_SWAP_IQ, swap? 1 : 0); } - void set_offset(const std::complex &off){ - _iface->poke32(REG_RX_FE_OFFSET_I, fs_to_bits(off.real(), 24)); - _iface->poke32(REG_RX_FE_OFFSET_Q, fs_to_bits(off.imag(), 24)); + void set_dc_offset_auto(const bool enb){ + this->set_dc_offset(enb? 0 : OFFSET_FIXED); + } + + std::complex set_dc_offset(const std::complex &off){ + static const double scaler = double(1ul << 29); + _i_dc_off = boost::math::iround(off.real()*scaler); + _q_dc_off = boost::math::iround(off.imag()*scaler); + + this->set_dc_offset(OFFSET_SET | OFFSET_FIXED); + + return std::complex(_i_dc_off/scaler, _q_dc_off/scaler); + } + + void set_dc_offset(const boost::uint32_t flags){ + _iface->poke32(REG_RX_FE_OFFSET_I, flags | _i_dc_off); + _iface->poke32(REG_RX_FE_OFFSET_Q, flags | _q_dc_off); } void set_correction(const std::complex &cor){ @@ -52,6 +69,7 @@ public: } private: + boost::int32_t _i_dc_off, _q_dc_off; wb_iface::sptr _iface; const size_t _base; }; diff --git a/host/lib/usrp/cores/rx_frontend_core_200.hpp b/host/lib/usrp/cores/rx_frontend_core_200.hpp index a950e2bb7..73dfbdc72 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.hpp @@ -33,7 +33,9 @@ public: virtual void set_mux(const bool swap) = 0; - virtual void set_offset(const std::complex &off) = 0; + virtual void set_dc_offset_auto(const bool enb) = 0; + + virtual std::complex set_dc_offset(const std::complex &off) = 0; virtual void set_correction(const std::complex &cor) = 0; diff --git a/host/lib/usrp/cores/tx_frontend_core_200.cpp b/host/lib/usrp/cores/tx_frontend_core_200.cpp index a7568a81e..71555e47f 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.cpp @@ -50,9 +50,15 @@ public: _iface->poke32(REG_TX_FE_MUX, mode_to_mux[mode]); } - void set_dc_offset(const std::complex &off){ - _iface->poke32(REG_TX_FE_DC_OFFSET_I, fs_to_bits(off.real(), 24)); - _iface->poke32(REG_TX_FE_DC_OFFSET_Q, fs_to_bits(off.imag(), 24)); + std::complex set_dc_offset(const std::complex &off){ + static const double scaler = double(1ul << 23); + const boost::int32_t i_dc_off = boost::math::iround(off.real()*scaler); + const boost::int32_t q_dc_off = boost::math::iround(off.imag()*scaler); + + _iface->poke32(REG_TX_FE_DC_OFFSET_I, i_dc_off); + _iface->poke32(REG_TX_FE_DC_OFFSET_Q, q_dc_off); + + return std::complex(i_dc_off/scaler, q_dc_off/scaler); } void set_correction(const std::complex &cor){ diff --git a/host/lib/usrp/cores/tx_frontend_core_200.hpp b/host/lib/usrp/cores/tx_frontend_core_200.hpp index 9e4a7bc79..f905e447d 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.hpp @@ -33,7 +33,7 @@ public: virtual void set_mux(const std::string &mode) = 0; - virtual void set_dc_offset(const std::complex &off) = 0; + virtual std::complex set_dc_offset(const std::complex &off) = 0; virtual void set_correction(const std::complex &cor) = 0; -- cgit v1.2.3 From bd08f403e3936d9c35b04f8990605dd49310fbfd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:04:18 -0700 Subject: usrp: register properties for correction and dc offset --- host/lib/usrp/b100/b100_impl.cpp | 18 +++++++++++++++++- host/lib/usrp/e100/e100_impl.cpp | 18 +++++++++++++++++- host/lib/usrp/usrp2/usrp2_impl.cpp | 18 +++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index bb91d415d..ec31ce04e 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -276,12 +276,28 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// _rx_fe = rx_frontend_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_RX_FRONT)); _tx_fe = tx_frontend_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_TX_FRONT)); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_rx_subdev_spec, this, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 6cb404000..bdf5a9b85 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -250,12 +250,28 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// _rx_fe = rx_frontend_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_RX_FRONT)); _tx_fe = tx_frontend_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_TX_FRONT)); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_rx_subdev_spec, this, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 24178d10c..6f215471e 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -456,12 +456,28 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].tx_fe = tx_frontend_core_200::make( _mbc[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT) ); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _mbc[mb].rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _mbc[mb].tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////// -- cgit v1.2.3 From a62645089202ac2ac39a55c48d3876474b54223e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Oct 2011 10:36:41 -0700 Subject: usrp: prefer name iq_balance for api call --- host/include/uhd/usrp/multi_usrp.hpp | 11 +++++------ host/lib/usrp/b100/b100_impl.cpp | 8 ++++---- host/lib/usrp/cores/rx_frontend_core_200.cpp | 2 +- host/lib/usrp/cores/rx_frontend_core_200.hpp | 2 +- host/lib/usrp/cores/tx_frontend_core_200.cpp | 2 +- host/lib/usrp/cores/tx_frontend_core_200.hpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 8 ++++---- host/lib/usrp/multi_usrp.cpp | 12 ++++++------ host/lib/usrp/usrp2/usrp2_impl.cpp | 8 ++++---- 9 files changed, 27 insertions(+), 28 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 1cbe3a684..0cf50aa0d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -21,8 +21,7 @@ //define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API -#define UHD_USRP_MULTI_USRP_DC_OFFSET_API -#define UHD_USRP_MULTI_USRP_CORRECTION_API +#define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API #include #include @@ -555,13 +554,13 @@ public: virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; /*! - * Set the RX frontend IQ imbalance and gain correction. + * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * * \param correction the complex correction value * \param chan the channel index 0 to N-1 */ - virtual void set_rx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + virtual void set_rx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; /******************************************************************* * TX methods @@ -769,13 +768,13 @@ public: virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; /*! - * Set the TX frontend IQ imbalance and gain correction. + * Set the TX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * * \param correction the complex correction value * \param chan the channel index 0 to N-1 */ - virtual void set_tx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + virtual void set_tx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; }; diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index ec31ce04e..0edaac914 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -288,14 +288,14 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/cores/rx_frontend_core_200.cpp b/host/lib/usrp/cores/rx_frontend_core_200.cpp index bb87cb600..d42022947 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.cpp @@ -63,7 +63,7 @@ public: _iface->poke32(REG_RX_FE_OFFSET_Q, flags | _q_dc_off); } - void set_correction(const std::complex &cor){ + void set_iq_balance(const std::complex &cor){ _iface->poke32(REG_RX_FE_MAG_CORRECTION, fs_to_bits(std::abs(cor), 18)); _iface->poke32(REG_RX_FE_PHASE_CORRECTION, fs_to_bits(std::atan2(cor.real(), cor.imag()), 18)); } diff --git a/host/lib/usrp/cores/rx_frontend_core_200.hpp b/host/lib/usrp/cores/rx_frontend_core_200.hpp index 73dfbdc72..5755424c8 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.hpp @@ -37,7 +37,7 @@ public: virtual std::complex set_dc_offset(const std::complex &off) = 0; - virtual void set_correction(const std::complex &cor) = 0; + virtual void set_iq_balance(const std::complex &cor) = 0; }; diff --git a/host/lib/usrp/cores/tx_frontend_core_200.cpp b/host/lib/usrp/cores/tx_frontend_core_200.cpp index 71555e47f..327e8d344 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.cpp @@ -61,7 +61,7 @@ public: return std::complex(i_dc_off/scaler, q_dc_off/scaler); } - void set_correction(const std::complex &cor){ + void set_iq_balance(const std::complex &cor){ _iface->poke32(REG_TX_FE_MAG_CORRECTION, fs_to_bits(std::abs(cor), 18)); _iface->poke32(REG_TX_FE_PHASE_CORRECTION, fs_to_bits(std::atan2(cor.real(), cor.imag()), 18)); } diff --git a/host/lib/usrp/cores/tx_frontend_core_200.hpp b/host/lib/usrp/cores/tx_frontend_core_200.hpp index f905e447d..8ee0f3e6d 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.hpp @@ -35,7 +35,7 @@ public: virtual std::complex set_dc_offset(const std::complex &off) = 0; - virtual void set_correction(const std::complex &cor) = 0; + virtual void set_iq_balance(const std::complex &cor) = 0; }; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index bdf5a9b85..4c5f5f066 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -262,14 +262,14 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 5a6acc2c5..7b3890c9b 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -567,13 +567,13 @@ public: } } - void set_rx_correction(const std::complex &offset, size_t chan){ + void set_rx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + _tree->access >(rx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ - this->set_rx_correction(offset, c); + this->set_rx_iq_balance(offset, c); } } @@ -701,13 +701,13 @@ public: } } - void set_tx_correction(const std::complex &offset, size_t chan){ + void set_tx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + _tree->access >(tx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ - this->set_tx_correction(offset, c); + this->set_tx_iq_balance(offset, c); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 6f215471e..50916fb37 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -468,14 +468,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _mbc[mb].rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _mbc[mb].tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 8e439ac16137c649b2a296967efe86d346f3968a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Oct 2011 11:27:21 -0700 Subject: usrp: docs tweaks and renames to multi-usrp --- host/include/uhd/usrp/multi_usrp.hpp | 85 +++++++++++++++++------------------- host/lib/usrp/multi_usrp.cpp | 5 --- 2 files changed, 39 insertions(+), 51 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 0cf50aa0d..9bb5b4381 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -54,7 +53,7 @@ namespace uhd{ namespace usrp{ * In the single device, single channel case, these parameters can be unspecified. * * When using a single device with multiple channels: - * - Channel mapping is determined by the subdevice specifications + * - Channel mapping is determined by the frontend specifications * - All channels share a common RX sample rate * - All channels share a common TX sample rate * @@ -62,8 +61,8 @@ namespace uhd{ namespace usrp{ * - Channel mapping is determined by the device address arguments * - All boards share a common RX sample rate * - All boards share a common TX sample rate - * - All boards share a common RX subdevice specification size - * - All boards share a common TX subdevice specification size + * - All boards share a common RX frontend specification size + * - All boards share a common TX frontend specification size * - All boards must have synchronized times (see the set_time_*() calls) * * Example to setup channel mapping for multiple devices: @@ -75,13 +74,13 @@ namespace uhd{ namespace usrp{ * dev_addr["addr1"] = "192.168.10.3"; * multi_usrp::sptr dev = multi_usrp::make(dev_addr); * - * //set the board on 10.2 to use the A RX subdevice (RX channel 0) + * //set the board on 10.2 to use the A RX frontend (RX channel 0) * dev->set_rx_subdev_spec("A:A", 0); * - * //set the board on 10.3 to use the B RX subdevice (RX channel 1) + * //set the board on 10.3 to use the B RX frontend (RX channel 1) * dev->set_rx_subdev_spec("A:B", 1); * - * //set both boards to use the AB TX subdevice (TX channels 0 and 1) + * //set both boards to use the AB TX frontend (TX channels 0 and 1) * dev->set_tx_subdev_spec("A:AB", multi_usrp::ALL_MBOARDS); * * //now that all the channels are mapped, continue with configuration... @@ -316,30 +315,24 @@ public: * \return a vector of sensor names */ virtual std::vector get_mboard_sensor_names(size_t mboard = 0) = 0; - - /*! - * Get a handle to the mboard_iface object which controls peripheral access. - * \return a mboard_iface::sptr object - */ - virtual mboard_iface::sptr get_mboard_iface(size_t mboard) = 0; /******************************************************************* * RX methods ******************************************************************/ /*! - * Set the RX subdevice specification: + * Set the RX frontend specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. - * \param spec the new subdevice specification + * \param spec the new frontend specification * \param mboard the motherboard index 0 to M-1 */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; /*! - * Get the RX subdevice specification. + * Get the RX frontend specification. * \param mboard the motherboard index 0 to M-1 - * \return the subdevice specification in use + * \return the frontend specification in use */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard = 0) = 0; @@ -351,9 +344,9 @@ public: virtual size_t get_rx_num_channels(void) = 0; /*! - * Get the name of the RX subdevice. + * Get the name of the RX frontend. * \param chan the channel index 0 to N-1 - * \return the subdevice name + * \return the frontend name */ virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; @@ -453,28 +446,28 @@ public: virtual std::vector get_rx_gain_names(size_t chan = 0) = 0; /*! - * Select the RX antenna on the subdevice. + * Select the RX antenna on the frontend. * \param ant the antenna name * \param chan the channel index 0 to N-1 */ virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; /*! - * Get the selected RX antenna on the subdevice. + * Get the selected RX antenna on the frontend. * \param chan the channel index 0 to N-1 * \return the antenna name */ virtual std::string get_rx_antenna(size_t chan = 0) = 0; /*! - * Get a list of possible RX antennas on the subdevice. + * Get a list of possible RX antennas on the frontend. * \param chan the channel index 0 to N-1 * \return a vector of antenna names */ virtual std::vector get_rx_antennas(size_t chan = 0) = 0; /*! - * Get the locked status of the LO on the subdevice. + * Get the locked status of the LO on the frontend. * \param chan the channel index 0 to N-1 * \return true for locked */ @@ -483,21 +476,21 @@ public: } /*! - * Set the RX bandwidth on the subdevice. + * Set the RX bandwidth on the frontend. * \param bandwidth the bandwidth in Hz * \param chan the channel index 0 to N-1 */ virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get the RX bandwidth on the subdevice. + * Get the RX bandwidth on the frontend. * \param chan the channel index 0 to N-1 * \return the bandwidth in Hz */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; /*! - * Read the RSSI value on the RX subdevice. + * Read the RSSI value on the RX frontend. * \param chan the channel index 0 to N-1 * \return the rssi in dB * \throw exception if RSSI readback not supported @@ -507,7 +500,7 @@ public: } /*! - * Get the dboard interface object for the RX subdevice. + * Get the dboard interface object for the RX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. * Use at your own risk! * \param chan the channel index 0 to N-1 @@ -516,7 +509,7 @@ public: virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; /*! - * Get an RX subdevice sensor value. + * Get an RX frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object @@ -524,7 +517,7 @@ public: virtual sensor_value_t get_rx_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible RX subdevice sensor names. + * Get a list of possible RX frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ @@ -557,7 +550,7 @@ public: * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * - * \param correction the complex correction value + * \param correction the complex correction (1.0 is full-scale) * \param chan the channel index 0 to N-1 */ virtual void set_rx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; @@ -566,19 +559,19 @@ public: * TX methods ******************************************************************/ /*! - * Set the TX subdevice specification: + * Set the TX frontend specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. - * \param spec the new subdevice specification + * \param spec the new frontend specification * \param mboard the motherboard index 0 to M-1 */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; /*! - * Get the TX subdevice specification. + * Get the TX frontend specification. * \param mboard the motherboard index 0 to M-1 - * \return the subdevice specification in use + * \return the frontend specification in use */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard = 0) = 0; @@ -590,9 +583,9 @@ public: virtual size_t get_tx_num_channels(void) = 0; /*! - * Get the name of the TX subdevice. + * Get the name of the TX frontend. * \param chan the channel index 0 to N-1 - * \return the subdevice name + * \return the frontend name */ virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; @@ -692,28 +685,28 @@ public: virtual std::vector get_tx_gain_names(size_t chan = 0) = 0; /*! - * Select the TX antenna on the subdevice. + * Select the TX antenna on the frontend. * \param ant the antenna name * \param chan the channel index 0 to N-1 */ virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; /*! - * Get the selected TX antenna on the subdevice. + * Get the selected TX antenna on the frontend. * \param chan the channel index 0 to N-1 * \return the antenna name */ virtual std::string get_tx_antenna(size_t chan = 0) = 0; /*! - * Get a list of possible TX antennas on the subdevice. + * Get a list of possible TX antennas on the frontend. * \param chan the channel index 0 to N-1 * \return a vector of antenna names */ virtual std::vector get_tx_antennas(size_t chan = 0) = 0; /*! - * Get the locked status of the LO on the subdevice. + * Get the locked status of the LO on the frontend. * \param chan the channel index 0 to N-1 * \return true for locked */ @@ -722,21 +715,21 @@ public: } /*! - * Set the TX bandwidth on the subdevice. + * Set the TX bandwidth on the frontend. * \param bandwidth the bandwidth in Hz * \param chan the channel index 0 to N-1 */ virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get the TX bandwidth on the subdevice. + * Get the TX bandwidth on the frontend. * \param chan the channel index 0 to N-1 * \return the bandwidth in Hz */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; /*! - * Get the dboard interface object for the TX subdevice. + * Get the dboard interface object for the TX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. * Use at your own risk! * \param chan the channel index 0 to N-1 @@ -745,7 +738,7 @@ public: virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; /*! - * Get an TX subdevice sensor value. + * Get an TX frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object @@ -753,7 +746,7 @@ public: virtual sensor_value_t get_tx_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible TX subdevice sensor names. + * Get a list of possible TX frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ @@ -771,7 +764,7 @@ public: * Set the TX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * - * \param correction the complex correction value + * \param correction the complex correction (1.0 is full-scale) * \param chan the channel index 0 to N-1 */ virtual void set_tx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 7b3890c9b..7383fa3c0 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -429,10 +428,6 @@ public: return _tree->list(mb_root(mboard) / "sensors"); } - mboard_iface::sptr get_mboard_iface(size_t){ - return mboard_iface::sptr(); //not implemented - } - /******************************************************************* * RX methods ******************************************************************/ -- cgit v1.2.3 From 7f815e124f217f37eb5e612a34ec84c33043aa87 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 25 Oct 2011 18:04:32 -0700 Subject: usrp: placeholder for potential set_next_command_time call --- host/include/uhd/usrp/multi_usrp.hpp | 15 +++++++++++++++ host/lib/usrp/multi_usrp.cpp | 4 ++++ 2 files changed, 19 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 9bb5b4381..319301784 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -22,6 +22,7 @@ #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API +#define UHD_USRP_MULTI_USRP_COMMAND_TIME_API #include #include @@ -225,6 +226,20 @@ public: */ virtual bool get_time_synchronized(void) = 0; + /*! + * Set the time at which the next control command will take effect. + * + * The time spec setting only takes effect on the first command. + * Subsequent commands will be sent ASAP unless user set time again. + * A timed command will throttle/back-pressure all subsequent commands, + * assuming that the subsequent commands occur within the time-window. + * If the time spec is late, the command will be activated upon arrival. + * + * \param time_spec the time at which the next command will activate + * \param mboard which motherboard to set the config + */ + virtual void set_next_command_time(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + /*! * Issue a stream command to the usrp device. * This tells the usrp to send samples into the host. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 7383fa3c0..2e7c76a06 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -347,6 +347,10 @@ public: return true; } + void set_next_command_time(const time_spec_t &, size_t){ + throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); + } + void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){ if (chan != ALL_CHANS){ _tree->access(rx_dsp_root(chan) / "stream_cmd").set(stream_cmd); -- cgit v1.2.3 From dedfa65256470f31a20c99a210457937d3f36056 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 25 Oct 2011 19:26:11 -0700 Subject: usrp: reorganize frontend paths in tree for correction stuff --- host/lib/usrp/b100/b100_impl.cpp | 13 ++++++++----- host/lib/usrp/e100/e100_impl.cpp | 13 ++++++++----- host/lib/usrp/multi_usrp.cpp | 22 +++++++++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 5 +++-- host/lib/usrp/usrp2/usrp2_impl.cpp | 13 ++++++++----- 5 files changed, 44 insertions(+), 22 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 0edaac914..944b669b2 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -282,19 +282,22 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 4c5f5f066..064686dd2 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -256,19 +256,22 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 2e7c76a06..43534ff37 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -548,7 +548,7 @@ public: void set_rx_dc_offset(const bool enb, size_t chan){ if (chan != ALL_CHANS){ - _tree->access(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "enable").set(enb); + _tree->access(rx_fe_root(chan) / "dc_offset" / "enable").set(enb); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -558,7 +558,7 @@ public: void set_rx_dc_offset(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + _tree->access >(rx_fe_root(chan) / "dc_offset" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -568,7 +568,7 @@ public: void set_rx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); + _tree->access >(rx_fe_root(chan) / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -692,7 +692,7 @@ public: void set_tx_dc_offset(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + _tree->access >(tx_fe_root(chan) / "dc_offset" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ @@ -702,7 +702,7 @@ public: void set_tx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); + _tree->access >(tx_fe_root(chan) / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ @@ -758,6 +758,18 @@ private: return mb_root(mcp.mboard) / "tx_dsps" / name; } + fs_path rx_fe_root(const size_t chan){ + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan); + return mb_root(mcp.mboard) / "rx_frontends" / spec.db_name; + } + + fs_path tx_fe_root(const size_t chan){ + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan); + return mb_root(mcp.mboard) / "tx_frontends" / spec.db_name; + } + fs_path rx_rf_fe_root(const size_t chan){ mboard_chan_pair mcp = rx_chan_to_mcp(chan); const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index fcc4f36ae..6634b43da 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -272,10 +272,11 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ .subscribe(boost::bind(&usrp1_impl::update_tx_subdev_spec, this, _1)); BOOST_FOREACH(const std::string &db, _dbc.keys()){ - _tree->create >(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / db; + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&usrp1_impl::set_rx_dc_offset, this, db, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&usrp1_impl::set_enb_rx_dc_offset, this, db, _1)) .set(true); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 50916fb37..db707b6af 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -462,19 +462,22 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); -- cgit v1.2.3 From 3a9edd27d6976456ea9cf4565590d4dd5bee809c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 10:21:11 -0700 Subject: usrp: added called to query bw range as well --- host/include/uhd/usrp/multi_usrp.hpp | 15 +++++++++++++++ host/lib/usrp/multi_usrp.cpp | 8 ++++++++ 2 files changed, 23 insertions(+) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 319301784..0509c2f1d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -23,6 +23,7 @@ #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API #define UHD_USRP_MULTI_USRP_COMMAND_TIME_API +#define UHD_USRP_MULTI_USRP_BW_RANGE_API #include #include @@ -504,6 +505,13 @@ public: */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the range of the possible RX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_rx_bandwidth_range(size_t chan = 0) = 0; + /*! * Read the RSSI value on the RX frontend. * \param chan the channel index 0 to N-1 @@ -743,6 +751,13 @@ public: */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the range of the possible TX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_tx_bandwidth_range(size_t chan = 0) = 0; + /*! * Get the dboard interface object for the TX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 43534ff37..d53004259 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -534,6 +534,10 @@ public: return _tree->access(rx_rf_fe_root(chan) / "bandwidth" / "value").get(); } + meta_range_t get_rx_bandwidth_range(size_t chan){ + return _tree->access(rx_rf_fe_root(chan) / "bandwidth" / "range").get(); + } + dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _tree->access(rx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); } @@ -678,6 +682,10 @@ public: return _tree->access(tx_rf_fe_root(chan) / "bandwidth" / "value").get(); } + meta_range_t get_tx_bandwidth_range(size_t chan){ + return _tree->access(tx_rf_fe_root(chan) / "bandwidth" / "range").get(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tree->access(tx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); } -- cgit v1.2.3 From fbc5b54f49eec3f27e5a351d27260783898b0bea Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 19:23:24 -0700 Subject: somebody made a typo --- host/lib/usrp/b100/b100_impl.cpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 944b669b2..a047a9a53 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -283,7 +283,7 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 064686dd2..00916ec2b 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -257,7 +257,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index db707b6af..ac3ee2e69 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -463,7 +463,7 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) -- cgit v1.2.3 From 5cdbf5b36969e12b93e720f67102dd4ab246b074 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Nov 2011 20:29:18 -0700 Subject: usrp: multi usrp API tweak --- host/include/uhd/usrp/multi_usrp.hpp | 15 ++++++++++----- host/lib/usrp/multi_usrp.cpp | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 0509c2f1d..5ea00565a 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -228,18 +228,23 @@ public: virtual bool get_time_synchronized(void) = 0; /*! - * Set the time at which the next control command will take effect. + * Set the time at which the control commands will take effect. * - * The time spec setting only takes effect on the first command. - * Subsequent commands will be sent ASAP unless user set time again. - * A timed command will throttle/back-pressure all subsequent commands, + * A timed command will back-pressure all subsequent timed commands, * assuming that the subsequent commands occur within the time-window. * If the time spec is late, the command will be activated upon arrival. * * \param time_spec the time at which the next command will activate * \param mboard which motherboard to set the config */ - virtual void set_next_command_time(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + virtual void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Clear the command time so future commands are sent ASAP. + * + * \param mboard which motherboard to set the config + */ + virtual void clear_command_time(size_t mboard = ALL_MBOARDS) = 0; /*! * Issue a stream command to the usrp device. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index d53004259..1110f5ebd 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -347,7 +347,11 @@ public: return true; } - void set_next_command_time(const time_spec_t &, size_t){ + void set_command_time(const time_spec_t &, size_t){ + throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); + } + + void clear_command_time(size_t){ throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); } -- cgit v1.2.3 From 07fb8d2b82c59ddaf7722b12db8c1387011fb34b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Nov 2011 20:34:06 -0700 Subject: usrp: fix rate calculation logic --- host/lib/usrp/cores/rx_dsp_core_200.cpp | 3 +-- host/lib/usrp/cores/tx_dsp_core_200.cpp | 3 +-- host/lib/usrp/usrp1/io_impl.cpp | 6 ++---- host/tests/ranges_test.cpp | 13 +++++++++++++ 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 6d306d507..b97f9c58e 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -149,8 +149,7 @@ public: } double set_host_rate(const double rate){ - const size_t decim_rate = this->get_host_rates().clip( - boost::math::iround(_tick_rate/rate), true); + const size_t decim_rate = boost::math::iround(_tick_rate/this->get_host_rates().clip(rate, true)); size_t decim = decim_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 1d571ea7c..9d90d30cc 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -89,8 +89,7 @@ public: } double set_host_rate(const double rate){ - const size_t interp_rate = this->get_host_rates().clip( - boost::math::iround(_tick_rate/rate), true); + const size_t interp_rate = boost::math::iround(_tick_rate/this->get_host_rates().clip(rate, true)); size_t interp = interp_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 31c834109..937706fdd 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -470,8 +470,7 @@ uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; - const size_t rate = this->get_rx_dsp_host_rates().clip( - boost::math::iround(_master_clock_rate / samp_rate), true); + const size_t rate = boost::math::iround(_master_clock_rate/this->get_rx_dsp_host_rates().clip(samp_rate, true)); if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" @@ -499,8 +498,7 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_tx_halfband()? 2 : 1; - const size_t rate = this->get_tx_dsp_host_rates().clip( - boost::math::iround(_master_clock_rate / samp_rate), true); + const size_t rate = boost::math::iround(_master_clock_rate/this->get_tx_dsp_host_rates().clip(samp_rate, true)); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); diff --git a/host/tests/ranges_test.cpp b/host/tests/ranges_test.cpp index 5f6de4645..85bb4c3c4 100644 --- a/host/tests/ranges_test.cpp +++ b/host/tests/ranges_test.cpp @@ -55,3 +55,16 @@ BOOST_AUTO_TEST_CASE(test_ranges_clip){ BOOST_CHECK_CLOSE(mr.clip(50.9, false), 50.9, tolerance); BOOST_CHECK_CLOSE(mr.clip(50.9, true), 51.0, tolerance); } + +BOOST_AUTO_TEST_CASE(test_ranges_clip2){ + meta_range_t mr; + mr.push_back(range_t(1.)); + mr.push_back(range_t(2.)); + mr.push_back(range_t(3.)); + + BOOST_CHECK_CLOSE(mr.clip(2., true), 2., tolerance); + BOOST_CHECK_CLOSE(mr.clip(0., true), 1., tolerance); + BOOST_CHECK_CLOSE(mr.clip(1.2, true), 1., tolerance); + BOOST_CHECK_CLOSE(mr.clip(3.1, true), 3., tolerance); + BOOST_CHECK_CLOSE(mr.clip(4., true), 3., tolerance); +} -- cgit v1.2.3 From 69adaee902c5f409ebd7844667a0c253d7a06c6a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 19:31:35 -0700 Subject: usrp2: reg map change for GPIO core --- host/lib/usrp/cores/gpio_core_200.cpp | 12 ++++++------ host/lib/usrp/cores/gpio_core_200.hpp | 2 +- host/lib/usrp/usrp2/dboard_iface.cpp | 2 +- host/lib/usrp/usrp2/fw_common.h | 2 +- host/lib/usrp/usrp2/usrp2_regs.hpp | 2 ++ 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/cores/gpio_core_200.cpp b/host/lib/usrp/cores/gpio_core_200.cpp index 8639b1851..d756097ff 100644 --- a/host/lib/usrp/cores/gpio_core_200.cpp +++ b/host/lib/usrp/cores/gpio_core_200.cpp @@ -23,15 +23,14 @@ #define REG_GPIO_TX_ONLY _base + 8 #define REG_GPIO_BOTH _base + 12 #define REG_GPIO_DDR _base + 16 -#define REG_GPIO_READ _base + 0 //any address will readback using namespace uhd; using namespace usrp; class gpio_core_200_impl : public gpio_core_200{ public: - gpio_core_200_impl(wb_iface::sptr iface, const size_t base): - _iface(iface), _base(base) { /* NOP */ } + gpio_core_200_impl(wb_iface::sptr iface, const size_t base, const size_t rb_addr): + _iface(iface), _base(base), _rb_addr(rb_addr) { /* NOP */ } void set_pin_ctrl(const unit_t unit, const boost::uint16_t value){ _pin_ctrl[unit] = value; //shadow @@ -57,12 +56,13 @@ public: } boost::uint16_t read_gpio(const unit_t unit){ - return boost::uint16_t(_iface->peek32(REG_GPIO_READ) >> unit2shit(unit)); + return boost::uint16_t(_iface->peek32(_rb_addr) >> unit2shit(unit)); } private: wb_iface::sptr _iface; const size_t _base; + const size_t _rb_addr; uhd::dict _pin_ctrl, _gpio_out, _gpio_ddr; uhd::dict > _atr_regs; @@ -95,6 +95,6 @@ private: }; -gpio_core_200::sptr gpio_core_200::make(wb_iface::sptr iface, const size_t base){ - return sptr(new gpio_core_200_impl(iface, base)); +gpio_core_200::sptr gpio_core_200::make(wb_iface::sptr iface, const size_t base, const size_t rb_addr){ + return sptr(new gpio_core_200_impl(iface, base, rb_addr)); } diff --git a/host/lib/usrp/cores/gpio_core_200.hpp b/host/lib/usrp/cores/gpio_core_200.hpp index 7ff2af649..278575874 100644 --- a/host/lib/usrp/cores/gpio_core_200.hpp +++ b/host/lib/usrp/cores/gpio_core_200.hpp @@ -33,7 +33,7 @@ public: typedef uhd::usrp::dboard_iface::atr_reg_t atr_reg_t; //! makes a new GPIO core from iface and slave base - static sptr make(wb_iface::sptr iface, const size_t base); + static sptr make(wb_iface::sptr iface, const size_t base, const size_t rb_addr); //! 1 = ATR virtual void set_pin_ctrl(const unit_t unit, const boost::uint16_t value) = 0; diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index c31fc52b7..bc510c8a1 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -107,7 +107,7 @@ usrp2_dboard_iface::usrp2_dboard_iface( ){ _iface = iface; _clock_ctrl = clock_ctrl; - _gpio = gpio_core_200::make(_iface, GPIO_BASE); + _gpio = gpio_core_200::make(_iface, U2_REG_SR_ADDR(SR_GPIO), U2_REG_GPIO_RB); //reset the aux dacs _dac_regs[UNIT_RX] = ad5623_regs_t(); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 7ad06f33f..62ba2d792 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,7 +30,7 @@ extern "C" { #endif //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 7 +#define USRP2_FPGA_COMPAT_NUM 8 #define USRP2_FW_COMPAT_NUM 11 #define USRP2_FW_VER_MINOR 0 diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 8839997f1..179a930c6 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -50,6 +50,7 @@ #define SR_TX_CTRL 144 // 6 #define SR_TX_DSP 160 // 5 +#define SR_GPIO 184 #define SR_UDP_SM 192 // 64 #define U2_REG_SR_ADDR(sr) (SETTING_REGS_BASE + (4 * (sr))) @@ -95,6 +96,7 @@ // Readback regs //////////////////////////////////////////////// #define U2_REG_STATUS READBACK_BASE + 4*8 +#define U2_REG_GPIO_RB READBACK_BASE + 4*9 #define U2_REG_TIME64_SECS_RB_IMM READBACK_BASE + 4*10 #define U2_REG_TIME64_TICKS_RB_IMM READBACK_BASE + 4*11 #define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12 -- cgit v1.2.3 From 0e7c8c388a5dcbd70631526b42e08178300b93c4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 Oct 2011 12:32:06 -0700 Subject: e100/b100: moved gpio regs and compat readback --- host/lib/usrp/b100/b100_impl.cpp | 14 ++++-- host/lib/usrp/b100/b100_impl.hpp | 2 +- host/lib/usrp/b100/b100_regs.hpp | 42 ++---------------- host/lib/usrp/b100/dboard_iface.cpp | 71 +++++------------------------- host/lib/usrp/e100/dboard_iface.cpp | 71 +++++------------------------- host/lib/usrp/e100/e100_impl.cpp | 26 +++++++---- host/lib/usrp/e100/e100_impl.hpp | 3 +- host/lib/usrp/e100/e100_regs.hpp | 42 ++---------------- host/usrp_e_utils/CMakeLists.txt | 2 - host/usrp_e_utils/usrp-e-debug-pins.c | 78 -------------------------------- host/usrp_e_utils/usrp-e-gpio.c | 83 ----------------------------------- 11 files changed, 58 insertions(+), 376 deletions(-) delete mode 100644 host/usrp_e_utils/usrp-e-debug-pins.c delete mode 100644 host/usrp_e_utils/usrp-e-gpio.c (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index a047a9a53..6bebc75ab 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -457,13 +457,19 @@ void b100_impl::check_fw_compat(void){ } void b100_impl::check_fpga_compat(void){ - const boost::uint16_t fpga_compat_num = _fpga_ctrl->peek16(B100_REG_MISC_COMPAT); - if (fpga_compat_num != B100_FPGA_COMPAT_NUM){ + const boost::uint32_t fpga_compat_num = _fpga_ctrl->peek32(B100_REG_RB_COMPAT); + boost::uint16_t fpga_major = fpga_compat_num >> 16, fpga_minor = fpga_compat_num & 0xffff; + if (fpga_major == 0){ //old version scheme + fpga_major = fpga_minor; + fpga_minor = 0; + } + if (fpga_major != B100_FPGA_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" + "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build." - ) % B100_FPGA_COMPAT_NUM % fpga_compat_num)); + ) % int(B100_FPGA_COMPAT_NUM) % fpga_major)); } + _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); } double b100_impl::update_rx_codec_gain(const double gain){ diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 25badc967..0984260be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -47,7 +47,7 @@ static const double B100_LINK_RATE_BPS = 256e6/8; //pratical link rate static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; static const boost::uint16_t B100_FW_COMPAT_NUM = 0x02; -static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x05; +static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x08; static const boost::uint32_t B100_RX_SID_BASE = 2; static const boost::uint32_t B100_TX_ASYNC_SID = 1; static const double B100_DEFAULT_TICK_RATE = 64e6; diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index 5e24f9937..491e16eef 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -31,7 +31,6 @@ #define B100_REG_MISC_RX_LEN B100_REG_MISC_BASE + 10 #define B100_REG_MISC_TX_LEN B100_REG_MISC_BASE + 12 #define B100_REG_MISC_XFER_RATE B100_REG_MISC_BASE + 14 -#define B100_REG_MISC_COMPAT B100_REG_MISC_BASE + 16 ///////////////////////////////////////////////////// // Slave 1 -- UART @@ -61,43 +60,6 @@ #define B100_REG_I2C_BASE B100_REG_SLAVE(3) -//////////////////////////////////////////////// -// Slave 4 -- GPIO - -#define B100_REG_GPIO_BASE B100_REG_SLAVE(4) - -#define B100_REG_GPIO_RX_IO B100_REG_GPIO_BASE + 0 -#define B100_REG_GPIO_TX_IO B100_REG_GPIO_BASE + 2 -#define B100_REG_GPIO_RX_DDR B100_REG_GPIO_BASE + 4 -#define B100_REG_GPIO_TX_DDR B100_REG_GPIO_BASE + 6 -#define B100_REG_GPIO_RX_SEL B100_REG_GPIO_BASE + 8 -#define B100_REG_GPIO_TX_SEL B100_REG_GPIO_BASE + 10 -#define B100_REG_GPIO_RX_DBG B100_REG_GPIO_BASE + 12 -#define B100_REG_GPIO_TX_DBG B100_REG_GPIO_BASE + 14 - -//possible bit values for sel when dbg is 0: -#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg -#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic - -//possible bit values for sel when dbg is 1: -#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric - -/////////////////////////////////////////////////// -// Slave 6 -- ATR Controller -// 16 regs - -#define B100_REG_ATR_BASE B100_REG_SLAVE(6) - -#define B100_REG_ATR_IDLE_RXSIDE B100_REG_ATR_BASE + 0 -#define B100_REG_ATR_IDLE_TXSIDE B100_REG_ATR_BASE + 2 -#define B100_REG_ATR_INTX_RXSIDE B100_REG_ATR_BASE + 4 -#define B100_REG_ATR_INTX_TXSIDE B100_REG_ATR_BASE + 6 -#define B100_REG_ATR_INRX_RXSIDE B100_REG_ATR_BASE + 8 -#define B100_REG_ATR_INRX_TXSIDE B100_REG_ATR_BASE + 10 -#define B100_REG_ATR_FULL_RXSIDE B100_REG_ATR_BASE + 12 -#define B100_REG_ATR_FULL_TXSIDE B100_REG_ATR_BASE + 14 - /////////////////////////////////////////////////// // Slave 7 -- Readback Mux 32 @@ -108,6 +70,8 @@ #define B100_REG_RB_TIME_PPS_SECS B100_REG_RB_MUX_32_BASE + 8 #define B100_REG_RB_TIME_PPS_TICKS B100_REG_RB_MUX_32_BASE + 12 #define B100_REG_RB_MISC_TEST32 B100_REG_RB_MUX_32_BASE + 16 +#define B100_REG_RB_COMPAT B100_REG_RB_MUX_32_BASE + 24 +#define B100_REG_RB_GPIO B100_REG_RB_MUX_32_BASE + 28 //////////////////////////////////////////////////// // Slaves 8 & 9 -- Settings Bus @@ -132,6 +96,8 @@ #define B100_SR_CLEAR_TX_FIFO 62 // 1 reg #define B100_SR_GLOBAL_RESET 63 // 1 reg +#define B100_SR_GPIO 128 + #define B100_REG_SR_ADDR(n) (B100_REG_SLAVE(8) + (4*(n))) #define B100_REG_SR_MISC_TEST32 B100_REG_SR_ADDR(B100_SR_REG_TEST32) diff --git a/host/lib/usrp/b100/dboard_iface.cpp b/host/lib/usrp/b100/dboard_iface.cpp index 229215a4e..39ad5c5ac 100644 --- a/host/lib/usrp/b100/dboard_iface.cpp +++ b/host/lib/usrp/b100/dboard_iface.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "wb_iface.hpp" +#include "gpio_core_200.hpp" #include #include "b100_regs.hpp" #include "clock_ctrl.hpp" @@ -45,13 +45,11 @@ public: _spi_iface = spi_iface; _clock = clock; _codec = codec; + _gpio = gpio_core_200::make(_wb_iface, B100_REG_SR_ADDR(B100_SR_GPIO), B100_REG_RB_GPIO); //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); - - _wb_iface->poke16(B100_REG_GPIO_RX_DBG, 0); - _wb_iface->poke16(B100_REG_GPIO_TX_DBG, 0); } ~b100_dboard_iface(void){ @@ -104,6 +102,7 @@ private: spi_iface::sptr _spi_iface; b100_clock_ctrl::sptr _clock; b100_codec_ctrl::sptr _codec; + gpio_core_200::sptr _gpio; }; /*********************************************************************** @@ -160,77 +159,27 @@ double b100_dboard_iface::get_codec_rate(unit_t){ * GPIO **********************************************************************/ void b100_dboard_iface::_set_pin_ctrl(unit_t unit, boost::uint16_t value){ - UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_SEL, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_SEL, value); return; - } + return _gpio->set_pin_ctrl(unit, value); } void b100_dboard_iface::_set_gpio_ddr(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_DDR, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_DDR, value); return; - } + return _gpio->set_gpio_ddr(unit, value); } void b100_dboard_iface::_set_gpio_out(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_IO, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_IO, value); return; - } + return _gpio->set_gpio_out(unit, value); } boost::uint16_t b100_dboard_iface::read_gpio(unit_t unit){ - switch(unit){ - case UNIT_RX: return _wb_iface->peek16(B100_REG_GPIO_RX_IO); - case UNIT_TX: return _wb_iface->peek16(B100_REG_GPIO_TX_IO); - default: UHD_THROW_INVALID_CODE_PATH(); - } + return _gpio->read_gpio(unit); } void b100_dboard_iface::_set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = map_list_of - (UNIT_RX, map_list_of - (ATR_REG_IDLE, B100_REG_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, B100_REG_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, B100_REG_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, B100_REG_ATR_FULL_RXSIDE) - ) - (UNIT_TX, map_list_of - (ATR_REG_IDLE, B100_REG_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, B100_REG_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, B100_REG_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, B100_REG_ATR_FULL_TXSIDE) - ) - ; - _wb_iface->poke16(unit_to_atr_to_addr[unit][atr], value); + return _gpio->set_atr_reg(unit, atr, value); } -void b100_dboard_iface::set_gpio_debug(unit_t unit, int which){ - //set this unit to all outputs - this->set_gpio_ddr(unit, 0xffff); - - //calculate the debug selections - boost::uint32_t dbg_sels = 0x0; - int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; - for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; - - //set the debug on and which debug selection - switch(unit){ - case UNIT_RX: - _wb_iface->poke16(B100_REG_GPIO_RX_DBG, 0xffff); - _wb_iface->poke16(B100_REG_GPIO_RX_SEL, dbg_sels); - return; - - case UNIT_TX: - _wb_iface->poke16(B100_REG_GPIO_TX_DBG, 0xffff); - _wb_iface->poke16(B100_REG_GPIO_TX_SEL, dbg_sels); - return; - } +void b100_dboard_iface::set_gpio_debug(unit_t, int){ + throw uhd::not_implemented_error("no set_gpio_debug implemented"); } /*********************************************************************** diff --git a/host/lib/usrp/e100/dboard_iface.cpp b/host/lib/usrp/e100/dboard_iface.cpp index d45577bd9..6afc7bc48 100644 --- a/host/lib/usrp/e100/dboard_iface.cpp +++ b/host/lib/usrp/e100/dboard_iface.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "wb_iface.hpp" +#include "gpio_core_200.hpp" #include #include "e100_regs.hpp" #include "clock_ctrl.hpp" @@ -45,13 +45,11 @@ public: _spi_iface = spi_iface; _clock = clock; _codec = codec; + _gpio = gpio_core_200::make(_wb_iface, E100_REG_SR_ADDR(UE_SR_GPIO), E100_REG_RB_GPIO); //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); - - _wb_iface->poke16(E100_REG_GPIO_RX_DBG, 0); - _wb_iface->poke16(E100_REG_GPIO_TX_DBG, 0); } ~e100_dboard_iface(void){ @@ -104,6 +102,7 @@ private: spi_iface::sptr _spi_iface; e100_clock_ctrl::sptr _clock; e100_codec_ctrl::sptr _codec; + gpio_core_200::sptr _gpio; }; /*********************************************************************** @@ -160,77 +159,27 @@ double e100_dboard_iface::get_codec_rate(unit_t){ * GPIO **********************************************************************/ void e100_dboard_iface::_set_pin_ctrl(unit_t unit, boost::uint16_t value){ - UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_SEL, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_SEL, value); return; - } + return _gpio->set_pin_ctrl(unit, value); } void e100_dboard_iface::_set_gpio_ddr(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_DDR, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_DDR, value); return; - } + return _gpio->set_gpio_ddr(unit, value); } void e100_dboard_iface::_set_gpio_out(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_IO, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_IO, value); return; - } + return _gpio->set_gpio_out(unit, value); } boost::uint16_t e100_dboard_iface::read_gpio(unit_t unit){ - switch(unit){ - case UNIT_RX: return _wb_iface->peek16(E100_REG_GPIO_RX_IO); - case UNIT_TX: return _wb_iface->peek16(E100_REG_GPIO_TX_IO); - default: UHD_THROW_INVALID_CODE_PATH(); - } + return _gpio->read_gpio(unit); } void e100_dboard_iface::_set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = map_list_of - (UNIT_RX, map_list_of - (ATR_REG_IDLE, E100_REG_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, E100_REG_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, E100_REG_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, E100_REG_ATR_FULL_RXSIDE) - ) - (UNIT_TX, map_list_of - (ATR_REG_IDLE, E100_REG_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, E100_REG_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, E100_REG_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, E100_REG_ATR_FULL_TXSIDE) - ) - ; - _wb_iface->poke16(unit_to_atr_to_addr[unit][atr], value); + return _gpio->set_atr_reg(unit, atr, value); } -void e100_dboard_iface::set_gpio_debug(unit_t unit, int which){ - //set this unit to all outputs - this->set_gpio_ddr(unit, 0xffff); - - //calculate the debug selections - boost::uint32_t dbg_sels = 0x0; - int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; - for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; - - //set the debug on and which debug selection - switch(unit){ - case UNIT_RX: - _wb_iface->poke16(E100_REG_GPIO_RX_DBG, 0xffff); - _wb_iface->poke16(E100_REG_GPIO_RX_SEL, dbg_sels); - return; - - case UNIT_TX: - _wb_iface->poke16(E100_REG_GPIO_TX_DBG, 0xffff); - _wb_iface->poke16(E100_REG_GPIO_TX_SEL, dbg_sels); - return; - } +void e100_dboard_iface::set_gpio_debug(unit_t, int){ + throw uhd::not_implemented_error("no set_gpio_debug implemented"); } /*********************************************************************** diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 00916ec2b..8fe9081b1 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -167,15 +167,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ ); //check that the compatibility is correct - const boost::uint16_t fpga_compat_num = _fpga_ctrl->peek16(E100_REG_MISC_COMPAT); - if (fpga_compat_num != E100_FPGA_COMPAT_NUM){ - throw uhd::runtime_error(str(boost::format( - "\nPlease update the FPGA image for your device.\n" - "See the application notes for USRP E-Series for instructions.\n" - "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" - "The FPGA build is not compatible with the host code build." - ) % E100_FPGA_COMPAT_NUM % fpga_compat_num)); - } + this->check_fpga_compat(); //////////////////////////////////////////////////////////////////// // Create controller objects @@ -455,3 +447,19 @@ sensor_value_t e100_impl::get_ref_locked(void){ const bool lock = _clock_ctrl->get_locked(); return sensor_value_t("Ref", lock, "locked", "unlocked"); } + +void e100_impl::check_fpga_compat(void){ + const boost::uint32_t fpga_compat_num = _fpga_ctrl->peek32(E100_REG_RB_COMPAT); + boost::uint16_t fpga_major = fpga_compat_num >> 16, fpga_minor = fpga_compat_num & 0xffff; + if (fpga_major == 0){ //old version scheme + fpga_major = fpga_minor; + fpga_minor = 0; + } + if (fpga_major != E100_FPGA_COMPAT_NUM){ + throw uhd::runtime_error(str(boost::format( + "Expected FPGA compatibility number %d, but got %d:\n" + "The FPGA build is not compatible with the host code build." + ) % int(E100_FPGA_COMPAT_NUM) % fpga_major)); + } + _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); +} diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index 954d6bd93..f3e481b93 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -48,7 +48,7 @@ static const double E100_RX_LINK_RATE_BPS = 166e6/3/2*2; static const double E100_TX_LINK_RATE_BPS = 166e6/3/1*2; static const std::string E100_I2C_DEV_NODE = "/dev/i2c-3"; static const std::string E100_UART_DEV_NODE = "/dev/ttyO0"; -static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x06; +static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x08; static const boost::uint32_t E100_RX_SID_BASE = 2; static const boost::uint32_t E100_TX_ASYNC_SID = 1; static const double E100_DEFAULT_CLOCK_RATE = 64e6; @@ -129,6 +129,7 @@ private: void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_clock_source(const std::string &); uhd::sensor_value_t get_ref_locked(void); + void check_fpga_compat(void); }; diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index 28ef707dc..f24f5895b 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -31,7 +31,6 @@ #define E100_REG_MISC_RX_LEN E100_REG_MISC_BASE + 10 #define E100_REG_MISC_TX_LEN E100_REG_MISC_BASE + 12 #define E100_REG_MISC_XFER_RATE E100_REG_MISC_BASE + 14 -#define E100_REG_MISC_COMPAT E100_REG_MISC_BASE + 16 ///////////////////////////////////////////////////// // Slave 1 -- UART @@ -67,43 +66,6 @@ #define E100_REG_ERR_BUFF E100_REG_SLAVE(5) -//////////////////////////////////////////////// -// Slave 4 -- GPIO - -#define E100_REG_GPIO_BASE E100_REG_SLAVE(4) - -#define E100_REG_GPIO_RX_IO E100_REG_GPIO_BASE + 0 -#define E100_REG_GPIO_TX_IO E100_REG_GPIO_BASE + 2 -#define E100_REG_GPIO_RX_DDR E100_REG_GPIO_BASE + 4 -#define E100_REG_GPIO_TX_DDR E100_REG_GPIO_BASE + 6 -#define E100_REG_GPIO_RX_SEL E100_REG_GPIO_BASE + 8 -#define E100_REG_GPIO_TX_SEL E100_REG_GPIO_BASE + 10 -#define E100_REG_GPIO_RX_DBG E100_REG_GPIO_BASE + 12 -#define E100_REG_GPIO_TX_DBG E100_REG_GPIO_BASE + 14 - -//possible bit values for sel when dbg is 0: -#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg -#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic - -//possible bit values for sel when dbg is 1: -#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric - -/////////////////////////////////////////////////// -// Slave 6 -- ATR Controller -// 16 regs - -#define E100_REG_ATR_BASE E100_REG_SLAVE(6) - -#define E100_REG_ATR_IDLE_RXSIDE E100_REG_ATR_BASE + 0 -#define E100_REG_ATR_IDLE_TXSIDE E100_REG_ATR_BASE + 2 -#define E100_REG_ATR_INTX_RXSIDE E100_REG_ATR_BASE + 4 -#define E100_REG_ATR_INTX_TXSIDE E100_REG_ATR_BASE + 6 -#define E100_REG_ATR_INRX_RXSIDE E100_REG_ATR_BASE + 8 -#define E100_REG_ATR_INRX_TXSIDE E100_REG_ATR_BASE + 10 -#define E100_REG_ATR_FULL_RXSIDE E100_REG_ATR_BASE + 12 -#define E100_REG_ATR_FULL_TXSIDE E100_REG_ATR_BASE + 14 - /////////////////////////////////////////////////// // Slave 7 -- Readback Mux 32 @@ -115,6 +77,8 @@ #define E100_REG_RB_TIME_PPS_TICKS E100_REG_RB_MUX_32_BASE + 12 #define E100_REG_RB_MISC_TEST32 E100_REG_RB_MUX_32_BASE + 16 #define E100_REG_RB_ERR_STATUS E100_REG_RB_MUX_32_BASE + 20 +#define E100_REG_RB_COMPAT E100_REG_RB_MUX_32_BASE + 24 +#define E100_REG_RB_GPIO E100_REG_RB_MUX_32_BASE + 28 //////////////////////////////////////////////////// // Slave 8 -- Settings Bus @@ -141,6 +105,8 @@ #define UE_SR_CLEAR_TX_FIFO 62 // 1 reg #define UE_SR_GLOBAL_RESET 63 // 1 reg +#define UE_SR_GPIO 128 + #define E100_REG_SR_ADDR(n) (E100_REG_SLAVE(8) + (4*(n))) #define E100_REG_SR_MISC_TEST32 E100_REG_SR_ADDR(UE_SR_REG_TEST32) diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index 721a40093..2b099cc5d 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -29,8 +29,6 @@ IF(ENABLE_USRP_E_UTILS) SET(usrp_e_utils_sources usrp-e-loopback.cpp usrp-e-wb-test.cpp - usrp-e-debug-pins.c - usrp-e-gpio.c ) #for each source: build an executable and install diff --git a/host/usrp_e_utils/usrp-e-debug-pins.c b/host/usrp_e_utils/usrp-e-debug-pins.c deleted file mode 100644 index 570ae63d8..000000000 --- a/host/usrp_e_utils/usrp-e-debug-pins.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include "e100_regs.hpp" - -// Usage: usrp_e_gpio - -static int fp; - -static int read_reg(__u16 reg) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - ret = ioctl(fp, USRP_E_READ_CTL16, &d); - return d.buf[0]; -} - -static void write_reg(__u16 reg, __u16 val) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - d.buf[0] = val; - ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -} - -int main(int argc, char *argv[]) -{ - int test; - - test = 0; - if (argc < 2) { - printf("%s 0|1|off\n", argv[0]); - return -1; - } - - fp = open("/dev/usrp_e0", O_RDWR); - printf("fp = %d\n", fp); - if (fp < 0) { - perror("Open failed"); - return -1; - } - - if (strcmp(argv[1], "0") == 0) { - printf("Selected 0 based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_TX_SEL, 0x0); - write_reg(E100_REG_GPIO_RX_SEL, 0x0); - write_reg(E100_REG_GPIO_TX_DBG, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DBG, 0xFFFF); - } else if (strcmp(argv[1], "1") == 0) { - printf("Selected 1 based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_TX_SEL, 0xFFFF); - write_reg(E100_REG_GPIO_RX_SEL, 0xFFFF); - write_reg(E100_REG_GPIO_TX_DBG, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DBG, 0xFFFF); - } else { - printf("Selected off based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - } - - return 0; -} diff --git a/host/usrp_e_utils/usrp-e-gpio.c b/host/usrp_e_utils/usrp-e-gpio.c deleted file mode 100644 index 4b788e945..000000000 --- a/host/usrp_e_utils/usrp-e-gpio.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "linux/usrp_e.h" -#include "e100_regs.hpp" - -// Usage: usrp_e_gpio - -static int fp; - -static int read_reg(__u16 reg) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - ret = ioctl(fp, USRP_E_READ_CTL16, &d); - return d.buf[0]; -} - -static void write_reg(__u16 reg, __u16 val) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - d.buf[0] = val; - ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -} - -int main(int argc, char *argv[]) -{ - int i, test, data_in; - - test = 0; - if (argc > 1) - test = 1; - - fp = open("/dev/usrp_e0", O_RDWR); - printf("fp = %d\n", fp); - - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - - for (i=0; i < 16; i++) { - write_reg(E100_REG_GPIO_RX_IO, 1 << i); - sleep(1); - if (test) { - data_in = read_reg(E100_REG_GPIO_TX_IO); - if (data_in != (1 << i)) - printf("Read failed, wrote: %X read: %X\n", \ - 1 << i, data_in); - } - } - - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - - sleep(1); - - for (i=0; i < 16; i++) { - write_reg(E100_REG_GPIO_TX_IO, 1 << i); - sleep(1); - if (test) { - data_in = read_reg(E100_REG_GPIO_RX_IO); - if (data_in != (1 << i)) - printf("Read failed, wrote: %X read: %X\n", \ - 1 << i, data_in); - } - } - - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - - return 0; -} -- cgit v1.2.3 From 9c598203327943b6ec042b031849ec6d7d907479 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 4 Nov 2011 23:23:47 +0000 Subject: e100/b100: init tree before filling it git log --- host/lib/usrp/b100/b100_impl.cpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 6bebc75ab..c15816cc2 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -139,6 +139,7 @@ UHD_STATIC_BLOCK(register_b100_device){ * Structors **********************************************************************/ b100_impl::b100_impl(const device_addr_t &device_addr){ + _tree = property_tree::make(); //extract the FPGA path for the B100 std::string b100_fpga_image = find_image_path( @@ -226,7 +227,6 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // Initialize the properties tree //////////////////////////////////////////////////////////////////// - _tree = property_tree::make(); _tree->create("/name").set("B-Series Device"); const fs_path mb_path = "/mboards/0"; _tree->create(mb_path / "name").set("B100 (B-Hundo)"); diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8fe9081b1..2e3a635a6 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -106,6 +106,7 @@ UHD_STATIC_BLOCK(register_e100_device){ * Structors **********************************************************************/ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ + _tree = property_tree::make(); //setup the main interface into fpga const std::string node = device_addr["node"]; @@ -179,7 +180,6 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // Initialize the properties tree //////////////////////////////////////////////////////////////////// - _tree = property_tree::make(); _tree->create("/name").set("E-Series Device"); const fs_path mb_path = "/mboards/0"; _tree->create(mb_path / "name").set(str(boost::format("%s (euewanee)") % model)); -- cgit v1.2.3 From 8bb81824ea3544352cf528cbd67efd04bde681c9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Nov 2011 12:14:14 -0700 Subject: usrp: parse rx stream args scalar --- host/lib/usrp/b100/io_impl.cpp | 3 ++- host/lib/usrp/e100/io_impl.cpp | 3 ++- host/lib/usrp/usrp2/io_impl.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 28b19f14e..abbd9864f 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -199,6 +199,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -228,7 +229,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ 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); + _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 )); diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index c47eb8940..3b0828b45 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -275,6 +275,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -304,7 +305,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ 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); + _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 )); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 660156285..d144c08bf 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -372,6 +372,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -406,7 +407,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ if (chan < num_chan_so_far){ const size_t dsp = num_chan_so_far - chan - 1; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, 0x400); + _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 )); -- cgit v1.2.3 From d9035414a27f484b89816e6e99c7f14d1769dee0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 30 Jul 2011 10:11:49 -0700 Subject: usrp: work on dboard code to use subtrees to populate frontend props --- host/include/uhd/usrp/dboard_base.hpp | 62 +------ host/include/uhd/usrp/dboard_manager.hpp | 24 +-- host/lib/usrp/b100/b100_impl.cpp | 21 +-- host/lib/usrp/dboard/CMakeLists.txt | 22 +-- host/lib/usrp/dboard_base.cpp | 41 +---- host/lib/usrp/dboard_ctor_args.hpp | 2 + host/lib/usrp/dboard_manager.cpp | 273 ++++--------------------------- host/lib/usrp/e100/e100_impl.cpp | 21 +-- host/lib/usrp/usrp1/usrp1_impl.cpp | 21 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 21 +-- 10 files changed, 85 insertions(+), 423 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index 7e9557a95..31b3643c7 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_USRP_DBOARD_BASE_HPP #include -#include +#include #include #include #include @@ -28,43 +28,6 @@ namespace uhd{ namespace usrp{ - /*! - * Possible subdev connection types: - * - * A complex subdevice is physically connected to both channels, - * which may be connected in one of two ways: IQ or QI (swapped). - * - * A real subdevice is only physically connected one channel, - * either only the I channel or only the Q channel. - */ - enum subdev_conn_t{ - SUBDEV_CONN_COMPLEX_IQ = 'C', - SUBDEV_CONN_COMPLEX_QI = 'c', - SUBDEV_CONN_REAL_I = 'R', - SUBDEV_CONN_REAL_Q = 'r' - }; - - /*! - * Possible device subdev properties - */ - enum subdev_prop_t{ - SUBDEV_PROP_NAME, //ro, std::string - SUBDEV_PROP_OTHERS, //ro, prop_names_t - SUBDEV_PROP_SENSOR, //ro, sensor_value_t - SUBDEV_PROP_SENSOR_NAMES, //ro, prop_names_t - SUBDEV_PROP_GAIN, //rw, double - SUBDEV_PROP_GAIN_RANGE, //ro, gain_range_t - SUBDEV_PROP_GAIN_NAMES, //ro, prop_names_t - SUBDEV_PROP_FREQ, //rw, double - SUBDEV_PROP_FREQ_RANGE, //ro, freq_range_t - SUBDEV_PROP_ANTENNA, //rw, std::string - SUBDEV_PROP_ANTENNA_NAMES, //ro, prop_names_t - SUBDEV_PROP_CONNECTION, //ro, subdev_conn_t - SUBDEV_PROP_ENABLED, //rw, bool - SUBDEV_PROP_USE_LO_OFFSET, //ro, bool - SUBDEV_PROP_BANDWIDTH //rw, double - }; - /*! * A daughter board dboard_base class for all dboards. * Only other dboard dboard_base classes should inherit this. @@ -81,19 +44,14 @@ public: //structors dboard_base(ctor_args_t); - virtual ~dboard_base(void); - - //interface - virtual void rx_get(const wax::obj &key, wax::obj &val) = 0; - virtual void rx_set(const wax::obj &key, const wax::obj &val) = 0; - virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; - virtual void tx_set(const wax::obj &key, const wax::obj &val) = 0; protected: std::string get_subdev_name(void); dboard_iface::sptr get_iface(void); dboard_id_t get_rx_id(void); dboard_id_t get_tx_id(void); + property_tree::sptr get_rx_subtree(void); + property_tree::sptr get_tx_subtree(void); private: UHD_PIMPL_DECL(impl) _impl; @@ -109,8 +67,6 @@ public: * Create a new xcvr dboard object, override in subclasses. */ xcvr_dboard_base(ctor_args_t); - - virtual ~xcvr_dboard_base(void); }; /*! @@ -123,12 +79,6 @@ public: * Create a new rx dboard object, override in subclasses. */ rx_dboard_base(ctor_args_t); - - virtual ~rx_dboard_base(void); - - //override here so the derived classes cannot - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); }; /*! @@ -141,12 +91,6 @@ public: * Create a new rx dboard object, override in subclasses. */ tx_dboard_base(ctor_args_t); - - virtual ~tx_dboard_base(void); - - //override here so the derived classes cannot - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); }; }} //namespace diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 091769a5c..d3a3ffb5c 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -20,11 +20,12 @@ #include #include -#include #include #include #include #include +#include +#include namespace uhd{ namespace usrp{ @@ -37,11 +38,6 @@ class UHD_API dboard_manager : boost::noncopyable{ public: typedef boost::shared_ptr sptr; - //! It does what it says... - static void populate_prop_tree_from_subdev( - property_tree::sptr subtree, wax::obj subdev - ); - //dboard constructor (each dboard should have a ::make with this signature) typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t); @@ -57,7 +53,7 @@ public: const dboard_id_t &dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names = prop_names_t(1, "0") + const std::vector &subdev_names = std::vector(1, "0") ); /*! @@ -74,27 +70,25 @@ public: const dboard_id_t &tx_dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names = prop_names_t(1, "0") + const std::vector &subdev_names = std::vector(1, "0") ); /*! * Make a new dboard manager. * \param rx_dboard_id the id of the rx dboard * \param tx_dboard_id the id of the tx dboard + * \param gdboard_id the id of the grand-dboard * \param iface the custom dboard interface + * \param subtree the subtree to load with props * \return an sptr to the new dboard manager */ static sptr make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_id_t gdboard_id, + dboard_iface::sptr iface, + property_tree::sptr subtree ); - - //dboard manager interface - virtual prop_names_t get_rx_subdev_names(void) = 0; - virtual prop_names_t get_tx_subdev_names(void) = 0; - virtual wax::obj get_rx_subdev(const std::string &subdev_name) = 0; - virtual wax::obj get_tx_subdev(const std::string &subdev_name) = 0; }; }} //namespace diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index c15816cc2..c506559be 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -404,22 +404,9 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _dboard_iface = make_b100_dboard_iface(_fpga_ctrl, _fpga_i2c_ctrl, _fpga_spi_ctrl, _clock_ctrl, _codec_ctrl); _tree->create(mb_path / "dboards/A/iface").set(_dboard_iface); _dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _dboard_manager->get_tx_subdev(name) - ); - } //initialize io handling this->io_init(); @@ -432,8 +419,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(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(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); - _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); + _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/rx_frontends").at(0))); + _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/tx_frontends").at(0))); _tree->access(mb_path / "clock_source/value").set("internal"); _tree->access(mb_path / "time_source/value").set("none"); } diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index c7b46e7c4..b5474ed16 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -20,16 +20,16 @@ ######################################################################## LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp ) diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp index e14c9d144..fe14c02b9 100644 --- a/host/lib/usrp/dboard_base.cpp +++ b/host/lib/usrp/dboard_base.cpp @@ -20,6 +20,7 @@ #include #include +using namespace uhd; using namespace uhd::usrp; /*********************************************************************** @@ -34,10 +35,6 @@ dboard_base::dboard_base(ctor_args_t args){ _impl->args = *static_cast(args); } -dboard_base::~dboard_base(void){ - /* NOP */ -} - std::string dboard_base::get_subdev_name(void){ return _impl->args.sd_name; } @@ -54,6 +51,14 @@ dboard_id_t dboard_base::get_tx_id(void){ return _impl->args.tx_id; } +property_tree::sptr dboard_base::get_rx_subtree(void){ + return _impl->args.rx_subtree; +} + +property_tree::sptr dboard_base::get_tx_subtree(void){ + return _impl->args.tx_subtree; +} + /*********************************************************************** * xcvr dboard dboard_base class **********************************************************************/ @@ -70,10 +75,6 @@ xcvr_dboard_base::xcvr_dboard_base(ctor_args_t args) : dboard_base(args){ } } -xcvr_dboard_base::~xcvr_dboard_base(void){ - /* NOP */ -} - /*********************************************************************** * rx dboard dboard_base class **********************************************************************/ @@ -86,18 +87,6 @@ rx_dboard_base::rx_dboard_base(ctor_args_t args) : dboard_base(args){ } } -rx_dboard_base::~rx_dboard_base(void){ - /* NOP */ -} - -void rx_dboard_base::tx_get(const wax::obj &, wax::obj &){ - throw uhd::runtime_error("cannot call tx_get on a rx dboard"); -} - -void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){ - throw uhd::runtime_error("cannot call tx_set on a rx dboard"); -} - /*********************************************************************** * tx dboard dboard_base class **********************************************************************/ @@ -109,15 +98,3 @@ tx_dboard_base::tx_dboard_base(ctor_args_t args) : dboard_base(args){ ) % get_rx_id().to_pp_string() % dboard_id_t::none().to_pp_string())); } } - -tx_dboard_base::~tx_dboard_base(void){ - /* NOP */ -} - -void tx_dboard_base::rx_get(const wax::obj &, wax::obj &){ - throw uhd::runtime_error("cannot call rx_get on a tx dboard"); -} - -void tx_dboard_base::rx_set(const wax::obj &, const wax::obj &){ - throw uhd::runtime_error("cannot call rx_set on a tx dboard"); -} diff --git a/host/lib/usrp/dboard_ctor_args.hpp b/host/lib/usrp/dboard_ctor_args.hpp index 708f2ea08..99c071ff8 100644 --- a/host/lib/usrp/dboard_ctor_args.hpp +++ b/host/lib/usrp/dboard_ctor_args.hpp @@ -18,6 +18,7 @@ #ifndef INCLUDED_LIBUHD_USRP_DBOARD_CTOR_ARGS_HPP #define INCLUDED_LIBUHD_USRP_DBOARD_CTOR_ARGS_HPP +#include #include #include #include @@ -29,6 +30,7 @@ namespace uhd{ namespace usrp{ std::string sd_name; dboard_iface::sptr db_iface; dboard_id_t rx_id, tx_id; + property_tree::sptr rx_subtree, tx_subtree; }; }} //namespace diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 0326c28ce..816fba0c4 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -79,7 +79,7 @@ bool operator==(const dboard_key_t &lhs, const dboard_key_t &rhs){ * storage and registering for dboards **********************************************************************/ //dboard registry tuple: dboard constructor, canonical name, subdev names -typedef boost::tuple args_t; +typedef boost::tuple > args_t; //map a dboard id to a dboard constructor typedef uhd::dict id_to_args_map_t; @@ -89,7 +89,7 @@ static void register_dboard_key( const dboard_key_t &dboard_key, dboard_manager::dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ UHD_LOGV(always) << "registering: " << name << std::endl; if (get_id_to_args_map().has_key(dboard_key)){ @@ -110,7 +110,7 @@ void dboard_manager::register_dboard( const dboard_id_t &dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ register_dboard_key(dboard_key_t(dboard_id), dboard_ctor, name, subdev_names); } @@ -120,7 +120,7 @@ void dboard_manager::register_dboard( const dboard_id_t &tx_dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ register_dboard_key(dboard_key_t(rx_dboard_id, tx_dboard_id), dboard_ctor, name, subdev_names); } @@ -143,46 +143,6 @@ std::string dboard_id_t::to_pp_string(void) const{ return str(boost::format("%s (%s)") % this->to_cname() % this->to_string()); } -/*********************************************************************** - * internal helper classes - **********************************************************************/ -/*! - * A special wax proxy object that forwards calls to a subdev. - * A sptr to an instance will be used in the properties structure. - */ -class subdev_proxy : boost::noncopyable, public wax::obj{ -public: - typedef boost::shared_ptr sptr; - enum type_t{RX_TYPE, TX_TYPE}; - - //structors - subdev_proxy(dboard_base::sptr subdev, type_t type): - _subdev(subdev), _type(type) - { - /* NOP */ - } - -private: - dboard_base::sptr _subdev; - type_t _type; - - //forward the get calls to the rx or tx - void get(const wax::obj &key, wax::obj &val){ - switch(_type){ - case RX_TYPE: return _subdev->rx_get(key, val); - case TX_TYPE: return _subdev->tx_get(key, val); - } - } - - //forward the set calls to the rx or tx - void set(const wax::obj &key, const wax::obj &val){ - switch(_type){ - case RX_TYPE: return _subdev->rx_set(key, val); - case TX_TYPE: return _subdev->tx_set(key, val); - } - } -}; - /*********************************************************************** * dboard manager implementation class **********************************************************************/ @@ -192,23 +152,18 @@ public: dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_iface::sptr iface, + property_tree::sptr subtree ); ~dboard_manager_impl(void); - //dboard_iface - prop_names_t get_rx_subdev_names(void); - prop_names_t get_tx_subdev_names(void); - wax::obj get_rx_subdev(const std::string &subdev_name); - wax::obj get_tx_subdev(const std::string &subdev_name); - private: - void init(dboard_id_t, dboard_id_t); + void init(dboard_id_t, dboard_id_t, property_tree::sptr); //list of rx and tx dboards in this dboard_manager //each dboard here is actually a subdevice proxy //the subdevice proxy is internal to the cpp file - uhd::dict _rx_dboards; - uhd::dict _tx_dboards; + uhd::dict _rx_dboards; + uhd::dict _tx_dboards; dboard_iface::sptr _iface; void set_nice_dboard_if(void); }; @@ -219,10 +174,16 @@ private: dboard_manager::sptr dboard_manager::make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_id_t gdboard_id, + dboard_iface::sptr iface, + property_tree::sptr subtree ){ return dboard_manager::sptr( - new dboard_manager_impl(rx_dboard_id, tx_dboard_id, iface) + new dboard_manager_impl( + rx_dboard_id, + (gdboard_id == dboard_id_t::none())? tx_dboard_id : gdboard_id, + iface, subtree + ) ); } @@ -232,21 +193,22 @@ dboard_manager::sptr dboard_manager::make( dboard_manager_impl::dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_iface::sptr iface, + property_tree::sptr subtree ): _iface(iface) { try{ - this->init(rx_dboard_id, tx_dboard_id); + this->init(rx_dboard_id, tx_dboard_id, subtree); } catch(const std::exception &e){ UHD_MSG(error) << "The daughterboard manager encountered a recoverable error in init" << std::endl << e.what(); - this->init(dboard_id_t::none(), dboard_id_t::none()); + this->init(dboard_id_t::none(), dboard_id_t::none(), subtree); } } void dboard_manager_impl::init( - dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id + dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, property_tree::sptr subtree ){ //find the dboard key matches for the dboard ids dboard_key_t rx_dboard_key, tx_dboard_key, xcvr_dboard_key; @@ -283,7 +245,7 @@ void dboard_manager_impl::init( if (xcvr_dboard_key.is_xcvr()){ //extract data for the xcvr dboard key - dboard_ctor_t dboard_ctor; std::string name; prop_names_t subdevs; + dboard_ctor_t dboard_ctor; std::string name; std::vector subdevs; boost::tie(dboard_ctor, name, subdevs) = get_id_to_args_map()[xcvr_dboard_key]; //create the xcvr object for each subdevice @@ -291,15 +253,11 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = rx_dboard_id; db_ctor_args.tx_id = tx_dboard_id; + db_ctor_args.rx_subtree = subtree->subtree("rx_frontends/" + subdev); + db_ctor_args.tx_subtree = subtree->subtree("tx_frontends/" + subdev); dboard_base::sptr xcvr_dboard = dboard_ctor(&db_ctor_args); - //create a rx proxy for this xcvr board - _rx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE) - ); - //create a tx proxy for this xcvr board - _tx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE) - ); + _rx_dboards[subdev] = xcvr_dboard; + _tx_dboards[subdev] = xcvr_dboard; } } @@ -312,7 +270,7 @@ void dboard_manager_impl::init( } //extract data for the rx dboard key - dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; + dboard_ctor_t rx_dboard_ctor; std::string rx_name; std::vector rx_subdevs; boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_id_to_args_map()[rx_dboard_key]; //make the rx subdevs @@ -320,11 +278,9 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = rx_dboard_id; db_ctor_args.tx_id = dboard_id_t::none(); - dboard_base::sptr rx_dboard = rx_dboard_ctor(&db_ctor_args); - //create a rx proxy for this rx board - _rx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE) - ); + db_ctor_args.rx_subtree = subtree->subtree("rx_frontends/" + subdev); + db_ctor_args.tx_subtree = property_tree::sptr(); //null + _rx_dboards[subdev] = rx_dboard_ctor(&db_ctor_args); } //force the tx key to the unknown board for bad combinations @@ -333,7 +289,7 @@ void dboard_manager_impl::init( } //extract data for the tx dboard key - dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; + dboard_ctor_t tx_dboard_ctor; std::string tx_name; std::vector tx_subdevs; boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_id_to_args_map()[tx_dboard_key]; //make the tx subdevs @@ -341,11 +297,9 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = dboard_id_t::none(); db_ctor_args.tx_id = tx_dboard_id; - dboard_base::sptr tx_dboard = tx_dboard_ctor(&db_ctor_args); - //create a tx proxy for this tx board - _tx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE) - ); + db_ctor_args.rx_subtree = property_tree::sptr(); //null + db_ctor_args.tx_subtree = subtree->subtree("tx_frontends/" + subdev); + _tx_dboards[subdev] = tx_dboard_ctor(&db_ctor_args); } } } @@ -354,30 +308,6 @@ dboard_manager_impl::~dboard_manager_impl(void){UHD_SAFE_CALL( set_nice_dboard_if(); )} -prop_names_t dboard_manager_impl::get_rx_subdev_names(void){ - return _rx_dboards.keys(); -} - -prop_names_t dboard_manager_impl::get_tx_subdev_names(void){ - return _tx_dboards.keys(); -} - -wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){ - if (not _rx_dboards.has_key(subdev_name)) throw uhd::key_error( - str(boost::format("Unknown rx subdev name %s") % subdev_name) - ); - //get a link to the rx subdev proxy - return _rx_dboards[subdev_name]->get_link(); -} - -wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ - if (not _tx_dboards.has_key(subdev_name)) throw uhd::key_error( - str(boost::format("Unknown tx subdev name %s") % subdev_name) - ); - //get a link to the tx subdev proxy - return _tx_dboards[subdev_name]->get_link(); -} - void dboard_manager_impl::set_nice_dboard_if(void){ //make a list of possible unit types std::vector units = boost::assign::list_of @@ -392,137 +322,4 @@ void dboard_manager_impl::set_nice_dboard_if(void){ _iface->set_pin_ctrl(unit, 0x0000); //all gpio _iface->set_clock_enabled(unit, false); //clock off } - - //disable all rx subdevices - BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){ - this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; - } - - //disable all tx subdevices - BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){ - this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; - } -} - -/*********************************************************************** - * Populate a properties tree from a subdev waxy object - **********************************************************************/ -#include -#include - -static sensor_value_t get_sensor(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_SENSOR, name)].as(); -} - -static void set_gain(wax::obj subdev, const std::string &name, const double gain){ - subdev[named_prop_t(SUBDEV_PROP_GAIN, name)] = gain; -} - -static double get_gain(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as(); -} - -static meta_range_t get_gain_range(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_GAIN_RANGE, name)].as(); -} - -static void set_freq(wax::obj subdev, const double freq){ - subdev[SUBDEV_PROP_FREQ] = freq; -} - -static double get_freq(wax::obj subdev){ - return subdev[SUBDEV_PROP_FREQ].as(); -} - -static meta_range_t get_freq_range(wax::obj subdev){ - return subdev[SUBDEV_PROP_FREQ_RANGE].as(); -} - -static void set_ant(wax::obj subdev, const std::string &ant){ - subdev[SUBDEV_PROP_ANTENNA] = ant; -} - -static std::string get_ant(wax::obj subdev){ - return subdev[SUBDEV_PROP_ANTENNA].as(); -} - -static std::vector get_ants(wax::obj subdev){ - return subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); -} - -static std::string get_conn(wax::obj subdev){ - switch(subdev[SUBDEV_PROP_CONNECTION].as()){ - case SUBDEV_CONN_COMPLEX_IQ: return "IQ"; - case SUBDEV_CONN_COMPLEX_QI: return "QI"; - case SUBDEV_CONN_REAL_I: return "I"; - case SUBDEV_CONN_REAL_Q: return "Q"; - } - UHD_THROW_INVALID_CODE_PATH(); -} - -static bool get_use_lo_off(wax::obj subdev){ - return subdev[SUBDEV_PROP_USE_LO_OFFSET].as(); -} - -static bool get_set_enb(wax::obj subdev, const bool enb){ - subdev[SUBDEV_PROP_ENABLED] = enb; - return subdev[SUBDEV_PROP_ENABLED].as(); -} - -static void set_bw(wax::obj subdev, const double freq){ - subdev[SUBDEV_PROP_BANDWIDTH] = freq; -} - -static double get_bw(wax::obj subdev){ - return subdev[SUBDEV_PROP_BANDWIDTH].as(); -} - -void dboard_manager::populate_prop_tree_from_subdev( - property_tree::sptr subtree, wax::obj subdev -){ - subtree->create("name").set(subdev[SUBDEV_PROP_NAME].as()); - - const prop_names_t sensor_names = subdev[SUBDEV_PROP_SENSOR_NAMES].as(); - subtree->create("sensors"); //phony property so this dir exists - BOOST_FOREACH(const std::string &name, sensor_names){ - subtree->create("sensors/" + name) - .publish(boost::bind(&get_sensor, subdev, name)); - } - - const prop_names_t gain_names = subdev[SUBDEV_PROP_GAIN_NAMES].as(); - subtree->create("gains"); //phony property so this dir exists - BOOST_FOREACH(const std::string &name, gain_names){ - subtree->create("gains/" + name + "/value") - .publish(boost::bind(&get_gain, subdev, name)) - .subscribe(boost::bind(&set_gain, subdev, name, _1)); - subtree->create("gains/" + name + "/range") - .publish(boost::bind(&get_gain_range, subdev, name)); - } - - subtree->create("freq/value") - .publish(boost::bind(&get_freq, subdev)) - .subscribe(boost::bind(&set_freq, subdev, _1)); - - subtree->create("freq/range") - .publish(boost::bind(&get_freq_range, subdev)); - - subtree->create("antenna/value") - .publish(boost::bind(&get_ant, subdev)) - .subscribe(boost::bind(&set_ant, subdev, _1)); - - subtree->create >("antenna/options") - .publish(boost::bind(&get_ants, subdev)); - - subtree->create("connection") - .publish(boost::bind(&get_conn, subdev)); - - subtree->create("enabled") - .coerce(boost::bind(&get_set_enb, subdev, _1)); - - subtree->create("use_lo_offset") - .publish(boost::bind(&get_use_lo_off, subdev)); - - subtree->create("bandwidth/value") - .publish(boost::bind(&get_bw, subdev)) - .subscribe(boost::bind(&set_bw, subdev, _1)); } diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 2e3a635a6..c0a8f46f3 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -370,22 +370,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _dboard_iface = make_e100_dboard_iface(_fpga_ctrl, _fpga_i2c_ctrl, _fpga_spi_ctrl, _clock_ctrl, _codec_ctrl); _tree->create(mb_path / "dboards/A/iface").set(_dboard_iface); _dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _dboard_manager->get_tx_subdev(name) - ); - } //initialize io handling this->io_init(); @@ -398,8 +385,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(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(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); - _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); + _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/rx_frontends").at(0))); + _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/tx_frontends").at(0))); _tree->access(mb_path / "clock_source/value").set("internal"); _tree->access(mb_path / "time_source/value").set("none"); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 6634b43da..4be5a3a2b 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -363,29 +363,16 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ ); _tree->create(mb_path / "dboards" / db/ "iface").set(_dbc[db].dboard_iface); _dbc[db].dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dbc[db].dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dbc[db].dboard_iface, _tree->subtree(mb_path / "dboards" / db) ); - BOOST_FOREACH(const std::string &name, _dbc[db].dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards" / db/ "rx_frontends" / name), - _dbc[db].dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dbc[db].dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards" / db/ "tx_frontends" / name), - _dbc[db].dboard_manager->get_tx_subdev(name) - ); - } //init the subdev specs if we have a dboard (wont leave this loop empty) if (rx_db_eeprom.id != dboard_id_t::none() or _rx_subdev_spec.empty()){ - _rx_subdev_spec = subdev_spec_t(db + ":" + _dbc[db].dboard_manager->get_rx_subdev_names()[0]); + _rx_subdev_spec = subdev_spec_t(db + ":" + _tree->list(mb_path / "dboards" / db / "rx_frontends").at(0)); } if (tx_db_eeprom.id != dboard_id_t::none() or _tx_subdev_spec.empty()){ - _tx_subdev_spec = subdev_spec_t(db + ":" + _dbc[db].dboard_manager->get_tx_subdev_names()[0]); + _tx_subdev_spec = subdev_spec_t(db + ":" + _tree->list(mb_path / "dboards" / db / "tx_frontends").at(0)); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index ac3ee2e69..bb3bfc7e4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -597,22 +597,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].dboard_iface = make_usrp2_dboard_iface(_mbc[mb].iface, _mbc[mb].clock); _tree->create(mb_path / "dboards/A/iface").set(_mbc[mb].dboard_iface); _mbc[mb].dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _mbc[mb].dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _mbc[mb].dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _mbc[mb].dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _mbc[mb].dboard_manager->get_tx_subdev(name) - ); - } } //initialize io handling @@ -623,8 +610,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ fs_path root = "/mboards/" + mb; - _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_rx_subdev_names()[0])); - _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_tx_subdev_names()[0])); + _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/rx_frontends").at(0))); + _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/tx_frontends").at(0))); _tree->access(root / "clock_source/value").set("internal"); _tree->access(root / "time_source/value").set("none"); -- cgit v1.2.3 From ef256d2f6c14006ba27eaf2ba1a7fba3a828420a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 30 Jul 2011 11:34:47 -0700 Subject: rfx: setup frontend property tree for rfx dboard --- host/lib/usrp/dboard/CMakeLists.txt | 2 +- host/lib/usrp/dboard/db_rfx.cpp | 320 ++++++++---------------------------- 2 files changed, 65 insertions(+), 257 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index b5474ed16..adaaab683 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -21,7 +21,7 @@ LIBUHD_APPEND_SOURCES( #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 14129ef72..3e6d89758 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -55,11 +56,9 @@ using namespace boost::assign; /*********************************************************************** * The RFX Series constants **********************************************************************/ -static const prop_names_t rfx_tx_antennas = list_of("TX/RX"); +static const std::vector rfx_tx_antennas = list_of("TX/RX"); -static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2"); - -static const uhd::dict rfx_tx_gain_ranges; //empty +static const std::vector rfx_rx_antennas = list_of("TX/RX")("RX2"); static const uhd::dict rfx_rx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 70, 0.022)) @@ -81,27 +80,17 @@ public: ); ~rfx_xcvr(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: const freq_range_t _freq_range; const uhd::dict _rx_gain_ranges; const uhd::dict _div2; - double _rx_lo_freq, _tx_lo_freq; std::string _rx_ant; uhd::dict _rx_gains; boost::uint16_t _power_up; - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); /*! * Set the LO frequency for the particular dboard unit. @@ -114,17 +103,18 @@ private: /*! * Get the lock detect status of the LO. * \param unit which unit rx or tx - * \return true for locked + * \return sensor for locked */ - bool get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + sensor_value_t get_locked(dboard_iface::unit_t unit){ + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the aux adc - * \return the rssi in dB + * \return the rssi sensor in dBm */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //RSSI from VAGC vs RF Power, Fig 34, pg 13 double max_power = -3.0; @@ -133,7 +123,8 @@ private: static const double rssi_dyn_range = 60; //calculate the rssi from the voltage double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B); - return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + const double rssi = max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + return sensor_value_t("RSSI", rssi, "dBm"); } }; @@ -192,6 +183,55 @@ rfx_xcvr::rfx_xcvr( ), _power_up((get_rx_id() == 0x0024 && get_tx_id() == 0x0028) ? POWER_IO : 0) { + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("RFX RX"); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&rfx_xcvr::get_locked, this, dboard_iface::UNIT_RX)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&rfx_xcvr::get_rssi, this)); + BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&rfx_xcvr::set_rx_gain, this, _1, name)) + .set(_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&rfx_xcvr::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((_freq_range.start() + _freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&rfx_xcvr::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(rfx_rx_antennas); + this->get_rx_subtree()->create("connection").set("QI"); + this->get_rx_subtree()->create("enabled").set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("RFX TX"); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&rfx_xcvr::get_locked, this, dboard_iface::UNIT_TX)); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&rfx_xcvr::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((_freq_range.start() + _freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&rfx_xcvr::set_tx_ant, this, _1)).set(rfx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(rfx_tx_antennas); + this->get_tx_subtree()->create("connection").set("IQ"); + this->get_tx_subtree()->create("enabled").set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset").set(true); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); @@ -213,15 +253,6 @@ rfx_xcvr::rfx_xcvr( this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, _power_up | ANT_XX | MIXER_DIS); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, _power_up | ANT_XX | MIXER_DIS); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, _power_up | ANT_RX2| MIXER_ENB); - - //set some default values - set_rx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0); - set_tx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){ - set_rx_gain(_rx_gain_ranges[name].start(), name); - } } rfx_xcvr::~rfx_xcvr(void){ @@ -267,20 +298,16 @@ static double rx_pga0_gain_to_dac_volts(double &gain, double range){ return dac_volts; } -void rfx_xcvr::set_tx_gain(double, const std::string &name){ - assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name"); - UHD_THROW_INVALID_CODE_PATH(); //no gains to set -} - -void rfx_xcvr::set_rx_gain(double gain, const std::string &name){ +double rfx_xcvr::set_rx_gain(double gain, const std::string &name){ assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name"); if(name == "PGA0"){ double dac_volts = rx_pga0_gain_to_dac_volts(gain, (_rx_gain_ranges["PGA0"].stop() - _rx_gain_ranges["PGA0"].start())); - _rx_gains[name] = gain; //write the new voltage to the aux dac this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, dac_volts); + + return gain; } else UHD_THROW_INVALID_CODE_PATH(); } @@ -288,14 +315,6 @@ void rfx_xcvr::set_rx_gain(double gain, const std::string &name){ /*********************************************************************** * Tuning **********************************************************************/ -void rfx_xcvr::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void rfx_xcvr::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} - double rfx_xcvr::set_lo_freq( dboard_iface::unit_t unit, double target_freq @@ -408,214 +427,3 @@ double rfx_xcvr::set_lo_freq( ) % (actual_freq/1e6) << std::endl; return actual_freq; } - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "rfx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(_rx_gain_ranges.keys(), key.name, "rfx rx gain name"); - val = _rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = _freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = rfx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - else if ((key.name == "rssi") and (get_rx_id() != 0x0024)) - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked"); - if (get_rx_id() != 0x0024) names.push_back("rssi"); - val = names; - } - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "RFX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_RANGE: - assert_has(rfx_tx_gain_ranges.keys(), key.name, "rfx tx gain name"); - //no controllable tx gains, will not get here - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(rfx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = _freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = rfx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = true; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "RFX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} -- cgit v1.2.3 From a445f30003c415843a779fd40e67eeb670ab5d29 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Thu, 22 Sep 2011 13:44:26 -0700 Subject: Port of daughterboards from wax to new property trees Ported: Basic/LF Unknown XCVR DBSRX DBSRX2 TVRX TVRX2 --- host/lib/usrp/dboard/CMakeLists.txt | 14 +- host/lib/usrp/dboard/db_basic_and_lf.cpp | 282 ++++++---------------- host/lib/usrp/dboard/db_dbsrx.cpp | 200 +++++----------- host/lib/usrp/dboard/db_dbsrx2.cpp | 194 +++++---------- host/lib/usrp/dboard/db_rfx.cpp | 4 + host/lib/usrp/dboard/db_tvrx.cpp | 175 ++++---------- host/lib/usrp/dboard/db_tvrx2.cpp | 309 ++++++++++-------------- host/lib/usrp/dboard/db_unknown.cpp | 246 +++++-------------- host/lib/usrp/dboard/db_xcvr2450.cpp | 397 +++++++++++-------------------- 9 files changed, 572 insertions(+), 1249 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index adaaab683..cb71e695b 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -20,16 +20,16 @@ ######################################################################## LIBUHD_APPEND_SOURCES( - #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp ) diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 86d86dda0..971ecaeda 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include using namespace uhd; @@ -48,9 +49,6 @@ public: basic_rx(ctor_args_t args, double max_freq); ~basic_rx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _max_freq; }; @@ -60,18 +58,15 @@ public: basic_tx(ctor_args_t args, double max_freq); ~basic_tx(void); - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: double _max_freq; }; -static const uhd::dict sd_name_to_conn = map_list_of - ("AB", SUBDEV_CONN_COMPLEX_IQ) - ("BA", SUBDEV_CONN_COMPLEX_QI) - ("A", SUBDEV_CONN_REAL_I) - ("B", SUBDEV_CONN_REAL_Q) +static const uhd::dict sd_name_to_conn = map_list_of + ("AB", "IQ") + ("BA", "QI") + ("A", "I") + ("B", "Q") ; /*********************************************************************** @@ -105,222 +100,95 @@ UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){ **********************************************************************/ basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){ _max_freq = max_freq; + //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_rx_subtree()->create("gains"); //phony property so this dir exists + this->get_rx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_rx_subtree()->create("freq/range") + .set(freq_range_t(-_max_freq, +_max_freq)); + this->get_rx_subtree()->create("antenna/value") + .set(""); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_rx_subtree()->create("sensors"); //phony property so this dir exists + this->get_rx_subtree()->create("connection") + .set(sd_name_to_conn[get_subdev_name()]); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); + + //enable RX dboard clock + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000); this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0xFFFF); this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0x0000); - //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); } basic_rx::~basic_rx(void){ /* NOP */ } -void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = std::string(str(boost::format("%s - %s") - % get_rx_id().to_pp_string() - % get_subdev_name() - )); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(-_max_freq, +_max_freq); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("no selectable antennas on this board"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << boost::format( - "%s: No tunable bandwidth, fixed filtered to %0.2fMHz" - ) % get_rx_id().to_pp_string() % _max_freq; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - /*********************************************************************** * Basic and LF TX dboard **********************************************************************/ basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args){ _max_freq = max_freq; //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); -} -basic_tx::~basic_tx(void){ - /* NOP */ -} - -void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = std::string(str(boost::format("%s - %s") - % get_tx_id().to_pp_string() + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() % get_subdev_name() - )); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(-_max_freq, +_max_freq); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq; - return; + ))); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_tx_subtree()->create("freq/range") + .set(freq_range_t(-_max_freq, +_max_freq)); + this->get_tx_subtree()->create("antenna/value") + .set(""); + this->get_tx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_tx_subtree()->create("sensors"); //phony property so this dir exists + this->get_tx_subtree()->create("connection") + .set(sd_name_to_conn[get_subdev_name()]); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(false); + this->get_tx_subtree()->create("bandwidth/value") + .set(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq); + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); + + //enable TX dboard clock + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - default: UHD_THROW_PROP_GET_ERROR(); - } + //set GPIOs to output 0x0000 to decrease noise pickup + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, 0x0000); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, 0xFFFF); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0x0000); } -void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("no selectable antennas on this board"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << boost::format( - "%s: No tunable bandwidth, fixed filtered to %0.2fMHz" - ) % get_tx_id().to_pp_string() % _max_freq; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } +basic_tx::~basic_tx(void){ + /* NOP */ } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index c65c52590..7a90467ef 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -46,9 +46,12 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t dbsrx_freq_range(0.8e9, 2.4e9); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t dbsrx_bandwidth_range(2.0*4.0e6, 2.0*33.0e6); + static const freq_range_t dbsrx_pfd_freq_range(0.15e6, 2.01e6); -static const prop_names_t dbsrx_antennas = list_of("J3"); +static const std::vector dbsrx_antennas = list_of("J3"); static const uhd::dict dbsrx_gain_ranges = map_list_of ("GC1", gain_range_t(0, 56, 0.5)) @@ -63,9 +66,6 @@ public: dbsrx(ctor_args_t args); ~dbsrx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _bandwidth; @@ -76,9 +76,9 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x65 : 0x67; }; - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0x5)); @@ -136,10 +136,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0x0, 0x0); //mask and return lock detect @@ -149,9 +149,8 @@ private: "DBSRX: locked %d" ) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - }; /*********************************************************************** @@ -190,30 +189,58 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ "Please see the daughterboard app notes" ) % this->get_rx_id().to_pp_string(); + //send initial register settings + this->send_reg(0x0, 0x5); + + //set defaults for LO, gains, and filter bandwidth + _bandwidth = 33e6; + + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&dbsrx::get_locked, this)); + BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&dbsrx::set_gain, this, _1, name)) + .set(dbsrx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(dbsrx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&dbsrx::set_lo_freq, this, _1)) + .set(dbsrx_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(dbsrx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(dbsrx_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(dbsrx_antennas); + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&dbsrx::set_bandwidth, this, _1)) + .set(2.0*_bandwidth); //_bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(dbsrx_bandwidth_range); + //enable only the clocks we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr if (this->get_iface()->get_special_props().soft_clock_divider){ - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock when on USRP1 } else{ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs } - - //send initial register settings - this->send_reg(0x0, 0x5); - - //set defaults for LO, gains, and filter bandwidth - _bandwidth = 33e6; - set_lo_freq(dbsrx_freq_range.start()); - - BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){ - set_gain(dbsrx_gain_ranges[name].start(), name); - } - - set_bandwidth(33e6); // default bandwidth from datasheet } dbsrx::~dbsrx(void){ @@ -223,7 +250,7 @@ dbsrx::~dbsrx(void){ /*********************************************************************** * Tuning **********************************************************************/ -void dbsrx::set_lo_freq(double target_freq){ +double dbsrx::set_lo_freq(double target_freq){ target_freq = dbsrx_freq_range.clip(target_freq); double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0; @@ -398,6 +425,8 @@ void dbsrx::set_lo_freq(double target_freq){ if (update_filter_settings) set_bandwidth(_bandwidth); get_locked(); + + return _lo_freq; } /*********************************************************************** @@ -456,7 +485,7 @@ static double gain_to_gc1_rfvga_dac(double &gain){ return dac_volts; } -void dbsrx::set_gain(double gain, const std::string &name){ +double dbsrx::set_gain(double gain, const std::string &name){ assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name"); if (name == "GC2"){ _max2118_write_regs.gc2 = gain_to_gc2_vga_reg(gain); @@ -468,14 +497,19 @@ void dbsrx::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx::set_bandwidth(double bandwidth){ +double dbsrx::set_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //clip the input - bandwidth = uhd::clip(bandwidth, 4e6, 33e6); + bandwidth = dbsrx_bandwidth_range.clip(bandwidth); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); @@ -492,109 +526,7 @@ void dbsrx::set_bandwidth(double bandwidth){ ) % (_bandwidth/1e6) % int(_max2118_write_regs.m_divider) % int(_max2118_write_regs.f_dac) << std::endl; this->send_reg(0x3, 0x4); -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "dbsrx gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(dbsrx_gain_ranges.keys(), key.name, "dbsrx gain name"); - val = dbsrx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(dbsrx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = dbsrx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = dbsrx_antennas.at(0); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = dbsrx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_bandwidth; //_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - assert_has(dbsrx_antennas, val.as(), "DBSRX antenna name"); - return; - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_bandwidth; } - diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp index f19236907..954d7083d 100644 --- a/host/lib/usrp/dboard/db_dbsrx2.cpp +++ b/host/lib/usrp/dboard/db_dbsrx2.cpp @@ -42,9 +42,12 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t dbsrx2_freq_range(0.8e9, 2.4e9); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t dbsrx2_bandwidth_range(2.0*4.0e6, 2.0*40.0e6); + static const int dbsrx2_ref_divider = 4; // Hitachi HMC426 divider (U7) -static const prop_names_t dbsrx2_antennas = list_of("J3"); +static const std::vector dbsrx2_antennas = list_of("J3"); static const uhd::dict dbsrx2_gain_ranges = map_list_of ("GC1", gain_range_t(0, 73, 0.05)) @@ -59,9 +62,6 @@ public: dbsrx2(ctor_args_t args); ~dbsrx2(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _bandwidth; @@ -72,9 +72,9 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; } - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0xB)); @@ -146,10 +146,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0xC, 0xD); //mask and return lock detect @@ -159,9 +159,8 @@ private: "DBSRX2 locked: %d" ) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - }; /*********************************************************************** @@ -182,28 +181,53 @@ UHD_STATIC_BLOCK(reg_dbsrx2_dboard){ * Structors **********************************************************************/ dbsrx2::dbsrx2(ctor_args_t args) : rx_dboard_base(args){ - //enable only the clocks we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs - //send initial register settings send_reg(0x0, 0xB); //for (boost::uint8_t addr=0; addr<=12; addr++) this->send_reg(addr, addr); - //set defaults for LO, gains - set_lo_freq(dbsrx2_freq_range.start()); + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&dbsrx2::get_locked, this)); BOOST_FOREACH(const std::string &name, dbsrx2_gain_ranges.keys()){ - set_gain(dbsrx2_gain_ranges[name].start(), name); + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&dbsrx2::set_gain, this, _1, name)) + .set(dbsrx2_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(dbsrx2_gain_ranges[name]); } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&dbsrx2::set_lo_freq, this, _1)) + .set(dbsrx2_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(dbsrx2_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(dbsrx2_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(dbsrx2_antennas); + this->get_rx_subtree()->create("connection") + .set("QI"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&dbsrx2::set_bandwidth, this, _1)) + .set(2.0*40.0e6); //bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(dbsrx2_bandwidth_range); - set_bandwidth(40e6); // default bandwidth from datasheet - get_locked(); + //enable only the clocks we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs - _max2112_write_regs.bbg = boost::math::iround(dbsrx2_gain_ranges["BBG"].start()); - send_reg(0x9, 0x9); + get_locked(); } dbsrx2::~dbsrx2(void){ @@ -213,8 +237,8 @@ dbsrx2::~dbsrx2(void){ /*********************************************************************** * Tuning **********************************************************************/ -void dbsrx2::set_lo_freq(double target_freq){ - //target_freq = uhd::clip(target_freq, dbsrx2_freq_range.min, dbsrx2_freq_range.max); +double dbsrx2::set_lo_freq(double target_freq){ + //target_freq = dbsrx2_freq_range.clip(target_freq); //variables used in the calculation below int scaler = target_freq > 1125e6 ? 2 : 4; @@ -257,6 +281,7 @@ void dbsrx2::set_lo_freq(double target_freq){ //FIXME: probably unnecessary to call get_locked here //get_locked(); + return _lo_freq; } /*********************************************************************** @@ -309,7 +334,7 @@ static double gain_to_gc1_rfvga_dac(double &gain){ return dac_volts; } -void dbsrx2::set_gain(double gain, const std::string &name){ +double dbsrx2::set_gain(double gain, const std::string &name){ assert_has(dbsrx2_gain_ranges.keys(), name, "dbsrx2 gain name"); if (name == "BBG"){ _max2112_write_regs.bbg = gain_to_bbg_vga_reg(gain); @@ -321,14 +346,19 @@ void dbsrx2::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx2::set_bandwidth(double bandwidth){ +double dbsrx2::set_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //clip the input - bandwidth = uhd::clip(bandwidth, 4e6, 40e6); + bandwidth = dbsrx2_bandwidth_range.clip(bandwidth); _max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12); _bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6; @@ -339,105 +369,7 @@ void dbsrx2::set_bandwidth(double bandwidth){ << std::endl; this->send_reg(0x8, 0x8); -} -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void dbsrx2::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "dbsrx2 gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(dbsrx2_gain_ranges.keys(), key.name, "dbsrx2 gain name"); - val = dbsrx2_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(dbsrx2_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = dbsrx2_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("J3"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = dbsrx2_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_bandwidth; } - -void dbsrx2::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3e6d89758..3896534cd 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -211,6 +211,8 @@ rfx_xcvr::rfx_xcvr( this->get_rx_subtree()->create("enabled").set(true); //always enabled this->get_rx_subtree()->create("use_lo_offset").set(false); this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); //////////////////////////////////////////////////////////////////// // Register TX properties @@ -231,6 +233,8 @@ rfx_xcvr::rfx_xcvr( this->get_tx_subtree()->create("enabled").set(true); //always enabled this->get_tx_subtree()->create("use_lo_offset").set(true); this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 907d798dd..dfa617e77 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -57,7 +57,7 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = list_of("RX"); +static const std::vector tvrx_antennas = list_of("RX"); static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -136,9 +136,6 @@ public: tvrx(ctor_args_t args); ~tvrx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: uhd::dict _gains; double _lo_freq; @@ -147,8 +144,8 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x61 : 0x60; //ok really? we could rename that call }; - void set_gain(double gain, const std::string &name); - void set_freq(double freq); + double set_gain(double gain, const std::string &name); + double set_freq(double freq); void update_regs(void){ byte_vector_t regs_vector(4); @@ -185,6 +182,39 @@ UHD_STATIC_BLOCK(reg_tvrx_dboard){ * Structors **********************************************************************/ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&tvrx::set_gain, this, _1, name)) + .set(get_tvrx_gain_ranges()[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(get_tvrx_gain_ranges()[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&tvrx::set_freq, this, _1)) + .set(tvrx_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(tvrx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(tvrx_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(tvrx_antennas); + this->get_rx_subtree()->create("connection") + .set("I"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(6.0e6); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(6.0e6, 6.0e6)); + + //enable only the clocks we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) @@ -317,7 +347,7 @@ static double if_gain_to_voltage(double gain){ return dac_volts; } -void tvrx::set_gain(double gain, const std::string &name){ +double tvrx::set_gain(double gain, const std::string &name){ assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, rf_gain_to_voltage(gain, _lo_freq)); @@ -327,6 +357,8 @@ void tvrx::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*! @@ -334,7 +366,7 @@ void tvrx::set_gain(double gain, const std::string &name){ * \param freq the requested frequency */ -void tvrx::set_freq(double freq) { +double tvrx::set_freq(double freq) { freq = tvrx_freq_range.clip(freq); std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); @@ -367,131 +399,6 @@ void tvrx::set_freq(double freq) { UHD_LOGV(often) << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; _lo_freq = actual_lo_freq; //for rx props -} - -/*********************************************************************** - * Get the alias frequency of frequency freq when sampled at fs. - * \param freq the frequency of interest - * \param fs the sample rate - * \return the alias frequency - **********************************************************************/ - -static double get_alias(double freq, double fs) { - double alias; - freq = fmod(freq, fs); - if(freq >= (fs/2)) { - alias = freq - fs; - } else { - alias = freq; - } - return alias; -} -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - double codec_rate; - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "tvrx gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(get_tvrx_gain_ranges().keys(), key.name, "tvrx gain name"); - val = get_tvrx_gain_ranges()[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(get_tvrx_gain_ranges().keys()); - return; - - case SUBDEV_PROP_FREQ: - /* - * so here we have to do some magic. because the TVRX uses a relatively high IF, - * we have to watch the sample rate to see if the IF will be aliased - * or if it will fall within Nyquist. - */ - codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); - val = (_lo_freq - tvrx_if_freq) + get_alias(tvrx_if_freq, codec_rate); - UHD_LOGV(often) - << "Getting TVRX freq..." << std::endl - << "\tCodec rate: " << codec_rate << std::endl - << "\tLO freq: " << _lo_freq << std::endl - << "\tIF freq: " << tvrx_if_freq << std::endl - << "\tAlias freq: " << get_alias(tvrx_if_freq, codec_rate) << std::endl - << "\tCalculated freq: " << val.as() << std::endl; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = tvrx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = tvrx_antennas.front(); //there's only one - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = tvrx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_REAL_I; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 6.0e6; - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_FREQ: - this->set_freq(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "TVRX: No tunable bandwidth, fixed filtered to 6MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + return _lo_freq; } - diff --git a/host/lib/usrp/dboard/db_tvrx2.cpp b/host/lib/usrp/dboard/db_tvrx2.cpp index 23f203b8c..628221527 100644 --- a/host/lib/usrp/dboard/db_tvrx2.cpp +++ b/host/lib/usrp/dboard/db_tvrx2.cpp @@ -704,14 +704,22 @@ static const std::vector tvrx2_tda18272_freq_map = li static const freq_range_t tvrx2_freq_range(42e6, 870e6); +static const freq_range_t tvrx2_bandwidth_range = list_of + (range_t(1.7e6)) + (range_t(6.0e6)) + (range_t(7.0e6)) + (range_t(8.0e6)) + (range_t(10.0e6)) +; + static const uhd::dict tvrx2_sd_name_to_antennas = map_list_of ("RX1", "J100") ("RX2", "J140") ; -static const uhd::dict tvrx2_sd_name_to_conn = map_list_of - ("RX1", SUBDEV_CONN_REAL_Q) - ("RX2", SUBDEV_CONN_REAL_I) +static const uhd::dict tvrx2_sd_name_to_conn = map_list_of + ("RX1", "Q") + ("RX2", "I") ; static const uhd::dict tvrx2_sd_name_to_i2c_addr = map_list_of @@ -745,9 +753,6 @@ public: tvrx2(ctor_args_t args); ~tvrx2(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _freq_scalar; double _lo_freq; @@ -760,12 +765,11 @@ private: bool _enabled; - void set_enabled(void); - void set_disabled(void); + bool set_enabled(bool); - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void set_scaled_rf_freq(double rf_freq); double get_scaled_rf_freq(void); @@ -825,10 +829,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0x5, 0x5); //return lock detect @@ -838,14 +842,15 @@ private: "TVRX2 (%s): locked %d" ) % (get_subdev_name()) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the registers - * \return the rssi in dB(m?) FIXME + * Read the RSSI from the aux adc + * \return the rssi sensor in dB(m?) FIXME */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //Launch RSSI calculation with MSM statemachine _tda18272hnm_regs.set_reg(0x19, 0x80); //set MSM_byte_1 for rssi calculation _tda18272hnm_regs.set_reg(0x1A, 0x01); //set MSM_byte_2 for launching rssi calculation @@ -859,14 +864,16 @@ private: //calculate the rssi from the voltage double rssi_dBuV = 40.0 + double(((110.0 - 40.0)/128.0) * _tda18272hnm_regs.get_reg(0x7)); - return rssi_dBuV - 107.0; //convert to dBm in 50ohm environment ( -108.8 if 75ohm ) FIXME + double rssi = rssi_dBuV - 107.0; //convert to dBm in 50ohm environment ( -108.8 if 75ohm ) FIXME + + return sensor_value_t("RSSI", rssi, "dBm"); } /*! * Read the Temperature from the registers * \return the temp in degC */ - double get_temp(void){ + sensor_value_t get_temp(void){ //Enable Temperature reading _tda18272hnm_regs.tm_on = tda18272hnm_regs_t::TM_ON_SENSOR_ON; send_reg(0x4, 0x4); @@ -882,7 +889,7 @@ private: _tda18272hnm_regs.tm_on = tda18272hnm_regs_t::TM_ON_SENSOR_OFF; send_reg(0x4, 0x4); - return (double(_tda18272hnm_regs.tm_d)); + return sensor_value_t("TEMP", double(_tda18272hnm_regs.tm_d), "degC"); } }; @@ -930,24 +937,64 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ ( 7, tvrx2_tda18272_rfcal_coeffs_t(10) ) ; - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0); // All unused in atr - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, OUTPUT_MASK); // Set outputs + //set defaults for LO, gains, and filter bandwidth + _bandwidth = 10e6; + + _if_freq = 12.5e6; - double ref_clock=0.0; + _enabled = false; - //configure ref_clock + //send initial register settings + //this->read_reg(0x0, 0x43); + //this->send_reg(0x0, 0x43); - /* - std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); - BOOST_FOREACH(ref_clock, uhd::sorted(clock_rates)){ - if (ref_clock < 16.0e6) continue; - if (ref_clock >= 16.0e6) break; + //send magic xtal_cal_dac setting + send_reg(0x65, 0x65); + + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&tvrx2::get_locked, this)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&tvrx2::get_rssi, this)); + this->get_rx_subtree()->create("sensors/temperature") + .publish(boost::bind(&tvrx2::get_temp, this)); + BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&tvrx2::set_gain, this, _1, name)); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(tvrx2_gain_ranges[name]); } - this->get_iface()->set_clock_rate(dboard_iface::UNIT_RX, ref_clock); - */ + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&tvrx2::set_lo_freq, this, _1)); + this->get_rx_subtree()->create("freq/range") + .set(tvrx2_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(tvrx2_sd_name_to_antennas[get_subdev_name()]); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of(tvrx2_sd_name_to_antennas[get_subdev_name()])); + this->get_rx_subtree()->create("connection") + .set(tvrx2_sd_name_to_conn[get_subdev_name()]); + this->get_rx_subtree()->create("enabled") + .coerce(boost::bind(&tvrx2::set_enabled, this, _1)) + .set(_enabled); + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&tvrx2::set_bandwidth, this, _1)) + .set(_bandwidth); + this->get_rx_subtree()->create("bandwidth/range") + .set(tvrx2_bandwidth_range); - ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0); // All unused in atr + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, OUTPUT_MASK); // Set outputs + + //configure ref_clock + double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); if (ref_clock == 64.0e6) { this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, REFCLOCK_DIV4); @@ -978,22 +1025,6 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ "TVRX2 (%s): Refclock %f Hz, scalar = %f" ) % (get_subdev_name()) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % _freq_scalar << std::endl; - //set defaults for LO, gains, and filter bandwidth - _bandwidth = 10e6; - - _if_freq = 12.5e6; - - _lo_freq = tvrx2_freq_range.start(); - - _enabled = false; - - //send initial register settings - //this->read_reg(0x0, 0x43); - //this->send_reg(0x0, 0x43); - - //send magic xtal_cal_dac setting - send_reg(0x65, 0x65); - _tda18272hnm_regs.irq_polarity = tda18272hnm_regs_t::IRQ_POLARITY_RAISED_VCC; _tda18272hnm_regs.irq_clear = tda18272hnm_regs_t::IRQ_CLEAR_TRUE; send_reg(0x37, 0x37); @@ -1013,39 +1044,47 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ transition_0(); } -void tvrx2::set_enabled(void){ - //setup tuner parameters - transition_1(); +bool tvrx2::set_enabled(bool enable){ + if (enable == _enabled) return _enabled; - transition_2(int(tvrx2_freq_range.start())); + if (enable and not _enabled){ + //setup tuner parameters + transition_1(); - test_rf_filter_robustness(); + transition_2(int(tvrx2_freq_range.start())); - BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ - set_gain(tvrx2_gain_ranges[name].start(), name); - } + test_rf_filter_robustness(); + + BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ + this->get_rx_subtree()->access("gains/"+name+"/value") + .set(tvrx2_gain_ranges[name].start()); + } + + this->get_rx_subtree()->access("bandwidth/value") + .set(_bandwidth); // default bandwidth from datasheet + + //transition_2 equivalent + this->get_rx_subtree()->access("freq/value") + .set(tvrx2_freq_range.start()); - set_bandwidth(_bandwidth); // default bandwidth from datasheet + //enter standby mode + transition_3(); + _enabled = true; - //transition_2 equivalent - set_lo_freq(tvrx2_freq_range.start()); + } else { + //enter standby mode + transition_3(); + _enabled = false; + } - //enter standby mode - transition_3(); - _enabled = true; + return _enabled; } tvrx2::~tvrx2(void){ UHD_LOGV(often) << boost::format( "TVRX2 (%s): Called Destructor" ) % (get_subdev_name()) << std::endl; - UHD_SAFE_CALL(if (_enabled) set_disabled();) -} - -void tvrx2::set_disabled(void){ - //enter standby mode - transition_3(); - _enabled = false; + UHD_SAFE_CALL(if (_enabled) set_enabled(false);) } @@ -1682,7 +1721,7 @@ void tvrx2::wait_irq(void){ /*********************************************************************** * Tuning **********************************************************************/ -void tvrx2::set_lo_freq(double target_freq){ +double tvrx2::set_lo_freq(double target_freq){ //target_freq = std::clip(target_freq, tvrx2_freq_range.min, tvrx2_freq_range.max); read_reg(0x6, 0x6); @@ -1711,7 +1750,9 @@ void tvrx2::set_lo_freq(double target_freq){ UHD_LOGV(often) << boost::format( "\nTVRX2 (%s): RSSI = %f dBm\n" - ) % (get_subdev_name()) % (get_rssi()) << std::endl; + ) % (get_subdev_name()) % (get_rssi().to_real()) << std::endl; + + return _lo_freq; } /*********************************************************************** @@ -1741,7 +1782,7 @@ static double gain_to_if_gain_dac(double &gain){ return dac_volts; } -void tvrx2::set_gain(double gain, const std::string &name){ +double tvrx2::set_gain(double gain, const std::string &name){ assert_has(tvrx2_gain_ranges.keys(), name, "tvrx2 gain name"); if (name == "IF"){ @@ -1752,6 +1793,8 @@ void tvrx2::set_gain(double gain, const std::string &name){ //shadow gain setting _gains[name] = gain; + + return gain; } /*********************************************************************** @@ -1780,7 +1823,10 @@ static tda18272hnm_regs_t::lp_fc_t bandwidth_to_lp_fc_reg(double &bandwidth){ UHD_THROW_INVALID_CODE_PATH(); } -void tvrx2::set_bandwidth(double bandwidth){ +double tvrx2::set_bandwidth(double bandwidth){ + //clip the input + bandwidth = tvrx2_bandwidth_range.clip(bandwidth); + //compute low pass cutoff frequency setting _tda18272hnm_regs.lp_fc = bandwidth_to_lp_fc_reg(bandwidth); @@ -1793,119 +1839,6 @@ void tvrx2::set_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "TVRX2 (%s) Bandwidth (lp_fc): %f Hz, reg: %d" ) % (get_subdev_name()) % _bandwidth % (int(_tda18272hnm_regs.lp_fc)) << std::endl; -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void tvrx2::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "tvrx2 gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(tvrx2_gain_ranges.keys(), key.name, "tvrx2 gain name"); - val = tvrx2_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(tvrx2_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = tvrx2_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = tvrx2_sd_name_to_antennas[get_subdev_name()]; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, tvrx2_sd_name_to_antennas[get_subdev_name()]); - return; - - case SUBDEV_PROP_CONNECTION: - val = tvrx2_sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = _enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - else if (key.name == "rssi") - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else if (key.name == "temperature") - val = sensor_value_t("TEMP", this->get_temp(), "degC"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked")("rssi")("temperature"); - val = names; - } - return; - case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + return _bandwidth; } - -void tvrx2::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_gain( val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - return; - - case SUBDEV_PROP_ENABLED: - if ((val.as())) this->set_enabled(); - else if (not (val.as())) this->set_disabled(); - - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 3a11f1e5b..2ed50cd91 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -64,17 +64,11 @@ static void warn_if_old_rfx(const dboard_id_t &dboard_id, const std::string &xx) class unknown_rx : public rx_dboard_base{ public: unknown_rx(ctor_args_t args); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); }; class unknown_tx : public tx_dboard_base{ public: unknown_tx(ctor_args_t args); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); }; /*********************************************************************** @@ -98,99 +92,35 @@ UHD_STATIC_BLOCK(reg_unknown_dboards){ **********************************************************************/ unknown_rx::unknown_rx(ctor_args_t args) : rx_dboard_base(args){ warn_if_old_rfx(this->get_rx_id(), "RX"); -} - -void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = "Unknown - " + get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 0.0; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("Unknown Daughterboard: No selectable antenna"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"; - return; - default: UHD_THROW_PROP_SET_ERROR(); - } + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_rx_subtree()->create("gains"); //phony property so this dir exists + this->get_rx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_rx_subtree()->create("freq/range") + .set(freq_range_t(double(0.0), double(0.0))); + this->get_rx_subtree()->create("antenna/value") + .set(""); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_rx_subtree()->create("sensors"); //phony property so this dir exists + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(double(0.0)); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(0.0, 0.0)); } /*********************************************************************** @@ -198,97 +128,33 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ **********************************************************************/ unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){ warn_if_old_rfx(this->get_tx_id(), "TX"); -} - -void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = "Unknown - " + get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 0.0; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("Unknown Daughterboard: No selectable antenna"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_tx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_tx_subtree()->create("freq/range") + .set(freq_range_t(double(0.0), double(0.0))); + this->get_tx_subtree()->create("antenna/value") + .set(""); + this->get_tx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_tx_subtree()->create("sensors"); //phony property so this dir exists + this->get_tx_subtree()->create("connection") + .set("IQ"); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(false); + this->get_tx_subtree()->create("bandwidth/value") + .set(double(0.0)); + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(0.0, 0.0)); } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index bfd4421b8..bdc6aa9fe 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -76,7 +76,22 @@ static const freq_range_t xcvr_freq_range = list_of (range_t(4.9e9, 6.0e9)) ; -static const prop_names_t xcvr_antennas = list_of("J1")("J2"); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t xcvr_tx_bandwidth_range = list_of + (range_t(2.0*12e6)) + (range_t(2.0*18e6)) + (range_t(2.0*24e6)) +; + +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t xcvr_rx_bandwidth_range = list_of + (range_t(2.0*0.9*7.5e6, 2.0*1.1*7.5e6)) + (range_t(2.0*0.9*9.5e6, 2.0*1.1*9.5e6)) + (range_t(2.0*0.9*14e6, 2.0*1.1*14e6)) + (range_t(2.0*0.9*18e6, 2.0*1.1*18e6)) +; + +static const std::vector xcvr_antennas = list_of("J1")("J2"); static const uhd::dict xcvr_tx_gain_ranges = map_list_of ("VGA", gain_range_t(0, 30, 0.5)) @@ -99,12 +114,6 @@ public: xcvr2450(ctor_args_t args); ~xcvr2450(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _rx_bandwidth, _tx_bandwidth; @@ -113,14 +122,14 @@ private: int _ad9515div; max2829_regs_t _max2829_regs; - void set_lo_freq(double target_freq); - void set_lo_freq_core(double target_freq); + double set_lo_freq(double target_freq); + double set_lo_freq_core(double target_freq); void set_tx_ant(const std::string &ant); void set_rx_ant(const std::string &ant); - void set_tx_gain(double gain, const std::string &name); - void set_rx_gain(double gain, const std::string &name); - void set_rx_bandwidth(double bandwidth); - void set_tx_bandwidth(double bandwidth); + double set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); + double set_rx_bandwidth(double bandwidth); + double set_tx_bandwidth(double bandwidth); void update_atr(void); void spi_reset(void); @@ -139,18 +148,19 @@ private: static bool is_highband(double freq){return freq > 3e9;} /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ - return (this->get_iface()->read_gpio(dboard_iface::UNIT_RX) & LOCKDET_RXIO) != 0; + sensor_value_t get_locked(void){ + const bool locked = (this->get_iface()->read_gpio(dboard_iface::UNIT_RX) & LOCKDET_RXIO) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the aux adc - * \return the rssi in dB + * \return the rssi sensor in dBm */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //*FIXME* RSSI depends on LNA Gain Setting (datasheet pg 16 top middle chart) double max_power = 0.0; switch(_max2829_regs.rx_lna_gain){ @@ -165,7 +175,8 @@ private: static const double rssi_dyn_range = 60; //calculate the rssi from the voltage double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B); - return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + double rssi = max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + return sensor_value_t("RSSI", rssi, "dBm"); } }; @@ -185,15 +196,6 @@ UHD_STATIC_BLOCK(reg_xcvr2450_dboard){ * Structors **********************************************************************/ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ - //enable only the clocks we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); - spi_reset(); //prepare the spi _rx_bandwidth = 9.5e6; @@ -222,16 +224,88 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ this->send_reg(reg); } - //set defaults for LO, gains, antennas - set_lo_freq(2.45e9); - set_rx_ant(xcvr_antennas.at(0)); - set_tx_ant(xcvr_antennas.at(1)); - BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){ - set_tx_gain(xcvr_tx_gain_ranges[name].start(), name); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&xcvr2450::get_locked, this)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&xcvr2450::get_rssi, this)); + BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) + .set(xcvr_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(xcvr_rx_gain_ranges[name]); } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) + .set(double(2.45e9)); + this->get_rx_subtree()->create("freq/range") + .set(xcvr_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&xcvr2450::set_rx_ant, this, _1)) + .set(xcvr_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(xcvr_antennas); + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&xcvr2450::set_rx_bandwidth, this, _1)) //complex bandpass bandwidth + .set(2.0*_rx_bandwidth); //_rx_bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(xcvr_rx_bandwidth_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name") + .set(get_tx_id().to_pp_string()); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&xcvr2450::get_locked, this)); BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ - set_rx_gain(xcvr_rx_gain_ranges[name].start(), name); + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) + .set(xcvr_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(xcvr_rx_gain_ranges[name]); } + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) + .set(double(2.45e9)); + this->get_tx_subtree()->create("freq/range") + .set(xcvr_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&xcvr2450::set_tx_ant, this, _1)) + .set(xcvr_antennas.at(1)); + this->get_tx_subtree()->create >("antenna/options") + .set(xcvr_antennas); + this->get_tx_subtree()->create("connection") + .set("IQ"); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(true); + this->get_tx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&xcvr2450::set_tx_bandwidth, this, _1)) //complex bandpass bandwidth + .set(2.0*_tx_bandwidth); //_tx_bandwidth in lowpass, convert to complex bandpass + this->get_tx_subtree()->create("bandwidth/range") + .set(xcvr_tx_bandwidth_range); + + //enable only the clocks we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); } xcvr2450::~xcvr2450(void){ @@ -249,6 +323,9 @@ void xcvr2450::spi_reset(void){ boost::this_thread::sleep(boost::posix_time::milliseconds(10)); } +/*********************************************************************** + * Update ATR regs which change with Antenna or Freq + **********************************************************************/ void xcvr2450::update_atr(void){ //calculate tx atr pins int band_sel = (xcvr2450::is_highband(_lo_freq))? HB_PA_TXIO : LB_PA_TXIO; @@ -274,17 +351,19 @@ void xcvr2450::update_atr(void){ /*********************************************************************** * Tuning **********************************************************************/ -void xcvr2450::set_lo_freq(double target_freq){ +double xcvr2450::set_lo_freq(double target_freq){ //tune the LO and sleep a bit for lock //if not locked, try some carrier offsets + double actual = 0.0; for (double offset = 0.0; offset <= 3e6; offset+=1e6){ - this->set_lo_freq_core(target_freq + offset); + actual = this->set_lo_freq_core(target_freq + offset); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); - if (this->get_locked()) return; + if (this->get_locked().to_bool()) break; } + return actual; } -void xcvr2450::set_lo_freq_core(double target_freq){ +double xcvr2450::set_lo_freq_core(double target_freq){ //clip the input to the range target_freq = xcvr_freq_range.clip(target_freq); @@ -348,6 +427,8 @@ void xcvr2450::set_lo_freq_core(double target_freq){ this->send_reg(0x5); _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_AUTOMATIC;; this->send_reg(0x5); + + return _lo_freq; } /*********************************************************************** @@ -441,7 +522,7 @@ static int gain_to_rx_lna_reg(double &gain){ return reg; } -void xcvr2450::set_tx_gain(double gain, const std::string &name){ +double xcvr2450::set_tx_gain(double gain, const std::string &name){ assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); if (name == "VGA"){ _max2829_regs.tx_vga_gain = gain_to_tx_vga_reg(gain); @@ -453,9 +534,11 @@ void xcvr2450::set_tx_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _tx_gains[name] = gain; + + return gain; } -void xcvr2450::set_rx_gain(double gain, const std::string &name){ +double xcvr2450::set_rx_gain(double gain, const std::string &name){ assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); if (name == "VGA"){ _max2829_regs.rx_vga_gain = gain_to_rx_vga_reg(gain); @@ -467,6 +550,8 @@ void xcvr2450::set_rx_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _rx_gains[name] = gain; + + return gain; } @@ -541,9 +626,12 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double UHD_THROW_INVALID_CODE_PATH(); } -void xcvr2450::set_rx_bandwidth(double bandwidth){ +double xcvr2450::set_rx_bandwidth(double bandwidth){ double requested_bandwidth = bandwidth; + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //compute coarse low pass cutoff frequency setting _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); @@ -559,9 +647,14 @@ void xcvr2450::set_rx_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "XCVR2450 RX Bandwidth (lp_fc): %f Hz, coarse reg: %d, fine reg: %d" ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; + + return 2.0*_rx_bandwidth; } -void xcvr2450::set_tx_bandwidth(double bandwidth){ +double xcvr2450::set_tx_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //compute coarse low pass cutoff frequency setting _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); @@ -574,219 +667,7 @@ void xcvr2450::set_tx_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "XCVR2450 TX Bandwidth (lp_fc): %f Hz, coarse reg: %d" ) % _tx_bandwidth % (int(_max2829_regs.tx_lpf_coarse_adj)) << std::endl; -} - - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "xcvr rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(xcvr_rx_gain_ranges.keys(), key.name, "xcvr rx gain name"); - val = xcvr_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(xcvr_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = xcvr_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = xcvr_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - else if (key.name == "rssi") - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked")("rssi"); - val = names; - } - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_rx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "xcvr tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(xcvr_tx_gain_ranges.keys(), key.name, "xcvr tx gain name"); - val = xcvr_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(xcvr_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = xcvr_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _tx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = xcvr_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_tx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - default: UHD_THROW_PROP_SET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_tx_bandwidth; } -- cgit v1.2.3 From 8a8dfe41f26ee276e0aded016a6e7bc8e7010a77 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 10:42:38 -0700 Subject: basic: disable dboard clocks by default --- host/lib/usrp/dboard/db_basic_and_lf.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 971ecaeda..53429a8c7 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -131,8 +131,8 @@ basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){ this->get_rx_subtree()->create("bandwidth/range") .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); - //enable RX dboard clock - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //disable RX dboard clock by default + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, false); //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000); @@ -180,8 +180,8 @@ basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args){ this->get_tx_subtree()->create("bandwidth/range") .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); - //enable TX dboard clock - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + //disable TX dboard clock by default + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, false); //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, 0x0000); -- cgit v1.2.3 From a0e9612f7a32c370f26d1b2db2eee7e692a8f8e9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 13:00:30 -0700 Subject: sbx: squashed Ben's SBX work --- host/lib/ic_reg_maps/CMakeLists.txt | 5 + host/lib/ic_reg_maps/gen_adf4351_regs.py | 138 ++++++ host/lib/usrp/dboard/CMakeLists.txt | 4 +- host/lib/usrp/dboard/db_sbx.cpp | 785 ------------------------------- host/lib/usrp/dboard/db_sbx_common.cpp | 514 ++++++++++++++++++++ host/lib/usrp/dboard/db_sbx_common.hpp | 233 +++++++++ host/lib/usrp/dboard/db_sbx_version3.cpp | 186 ++++++++ host/lib/usrp/dboard/db_sbx_version4.cpp | 189 ++++++++ 8 files changed, 1268 insertions(+), 786 deletions(-) create mode 100755 host/lib/ic_reg_maps/gen_adf4351_regs.py delete mode 100644 host/lib/usrp/dboard/db_sbx.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_common.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_common.hpp create mode 100644 host/lib/usrp/dboard/db_sbx_version3.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_version4.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index 46cf5a06a..dc2ab7847 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -27,6 +27,11 @@ LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_CURRENT_BINARY_DIR}/adf4350_regs.hpp ) +LIBUHD_PYTHON_GEN_SOURCE( + ${CMAKE_CURRENT_SOURCE_DIR}/gen_adf4351_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/adf4351_regs.hpp +) + LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_CURRENT_SOURCE_DIR}/gen_adf4360_regs.py ${CMAKE_CURRENT_BINARY_DIR}/adf4360_regs.hpp diff --git a/host/lib/ic_reg_maps/gen_adf4351_regs.py b/host/lib/ic_reg_maps/gen_adf4351_regs.py new file mode 100755 index 000000000..607b2979d --- /dev/null +++ b/host/lib/ic_reg_maps/gen_adf4351_regs.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# +# 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 . +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +frac_12_bit 0[3:14] 0 +int_16_bit 0[15:30] 0x23 +##reserved 0[31] 0 +######################################################################## +## address 1 +######################################################################## +mod_12_bit 1[3:14] 0xfff +phase_12_bit 1[15:26] 0 +prescaler 1[27] 0 4_5, 8_9 +phase_adjust 1[28] 0 +##reserved 1[29:31] 0 +######################################################################## +## address 2 +######################################################################## +counter_reset 2[3] 0 disabled, enabled +cp_three_state 2[4] 0 disabled, enabled +power_down 2[5] 0 disabled, enabled +pd_polarity 2[6] 1 negative, positive +ldp 2[7] 0 10ns, 6ns +ldf 2[8] 0 frac_n, int_n +#set $current_setting_enums = ', '.join(map(lambda x: '_'.join(("%0.2fma"%(round(x*31.27 + 31.27)/100)).split('.')), range(0,16))) +charge_pump_current 2[9:12] 5 $current_setting_enums +double_buffer 2[13] 0 disabled, enabled +r_counter_10_bit 2[14:23] 0 +reference_divide_by_2 2[24] 1 disabled, enabled +reference_doubler 2[25] 0 disabled, enabled +muxout 2[26:28] 1 3state, dvdd, dgnd, rdiv, ndiv, analog_ld, dld, reserved +low_noise_and_spur 2[29:30] 3 low_noise, reserved0, reserved1, low_spur +##reserved 2[31] 0 +######################################################################## +## address 3 +######################################################################## +clock_divider_12_bit 3[3:14] 0 +clock_div_mode 3[15:16] 0 clock_divider_off, fast_lock, resync_enable, reserved +##reserved 3[17] 0 +cycle_slip_reduction 3[18] 0 disabled, enabled +##reserved 3[19:20] 0 +charge_cancel 3[21] 0 +anti_backlash_pulse 3[22] 0 6ns, 3ns +band_select_mode 3[23] 0 low, high +##reserved 3[24:31] 0 +######################################################################## +## address 4 +######################################################################## +output_power 4[3:4] 3 m4dbm, m1dbm, 2dbm, 5dbm +rf_output_enable 4[5] 1 disabled, enabled +aux_output_power 4[6:7] 0 m4dbm, m1dbm, 2dbm, 5dbm +aux_output_enable 4[8] 0 disabled, enabled +aux_output_select 4[9] 1 divided, fundamental +mute_till_lock_detect 4[10] 0 mute_disabled, mute_enabled +vco_power_down 4[11] 0 vco_powered_up, vco_powered_down +band_select_clock_div 4[12:19] 0 +rf_divider_select 4[20:22] 5 div1, div2, div4, div8, div16, div32, div64 +feedback_select 4[23] 1 divided, fundamental +##reserved 4[24:31] 0 +######################################################################## +## address 5 +######################################################################## +##reserved 5[3:18] 0 +##reserved 5[19:20] 0 +##reserved 5[21] 0 +ld_pin_mode 5[22:23] 1 low0, dld, low, high +##reserved 5[24:31] 0 +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +BODY_TMPL="""\ +enum addr_t{ + ADDR_R0 = 0, + ADDR_R1 = 1, + ADDR_R2 = 2, + ADDR_R3 = 3, + ADDR_R4 = 4, + ADDR_R5 = 5 +}; + +boost::uint32_t get_reg(boost::uint8_t addr){ + boost::uint32_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; +} + +void set_reg(boost::uint8_t addr, boost::uint32_t reg){ + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask()); + #end for + break; + #end for + } +} +""" + +if __name__ == '__main__': + import common; common.generate( + name='adf4351_regs', + regs_tmpl=REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index cb71e695b..a865a7858 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -23,7 +23,9 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp diff --git a/host/lib/usrp/dboard/db_sbx.cpp b/host/lib/usrp/dboard/db_sbx.cpp deleted file mode 100644 index 40dbd286d..000000000 --- a/host/lib/usrp/dboard/db_sbx.cpp +++ /dev/null @@ -1,785 +0,0 @@ -// -// Copyright 2011 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 . -// - -// Common IO Pins -#define LO_LPF_EN (1 << 15) -#define ADF4350_CE (1 << 3) -#define ADF4350_PDBRF (1 << 2) -#define ADF4350_MUXOUT (1 << 1) // INPUT!!! -#define LOCKDET_MASK (1 << 0) // INPUT!!! - -// TX IO Pins -#define TRSW (1 << 14) // 0 = TX, 1 = RX -#define TX_LED_TXRX (1 << 7) // LED for TX Antenna Selection TX/RX -#define TX_LED_LD (1 << 6) // LED for TX Lock Detect -#define DIS_POWER_TX (1 << 5) // on UNIT_TX, 0 powers up TX -#define TX_ENABLE (1 << 4) // on UNIT_TX, 0 disables TX Mixer - -// RX IO Pins -#define LNASW (1 << 14) // 0 = TX/RX, 1 = RX2 -#define RX_LED_RX1RX2 (1 << 7) // LED for RX Antenna Selection RX1/RX2 -#define RX_LED_LD (1 << 6) // LED for RX Lock Detect -#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX -#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband - -// RX Attenuator Pins -#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// TX Attenuator Pins -#define TX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define TX_ATTN_MASK (63 << TX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// Mixer functions -#define TX_MIXER_ENB (ADF4350_PDBRF) -#define TX_MIXER_DIS 0 - -#define RX_MIXER_ENB (ADF4350_PDBRF) -#define RX_MIXER_DIS 0 - -// Pin functions -#define TX_LED_IO (TX_LED_TXRX|TX_LED_LD) // LED gpio lines, pull down for LED -#define TXIO_MASK (LO_LPF_EN|TRSW|ADF4350_CE|ADF4350_PDBRF|TX_ATTN_MASK|DIS_POWER_TX|TX_ENABLE) - -#define RX_LED_IO (RX_LED_RX1RX2|RX_LED_LD) // LED gpio lines, pull down for LED -#define RXIO_MASK (LO_LPF_EN|LNASW|ADF4350_CE|ADF4350_PDBRF|RX_ATTN_MASK|DIS_POWER_RX|RX_DISABLE) - -// Power functions -#define TX_POWER_UP (ADF4350_CE|TX_ENABLE) -#define TX_POWER_DOWN (DIS_POWER_TX) - -#define RX_POWER_UP (ADF4350_CE) -#define RX_POWER_DOWN (DIS_POWER_RX) - -// Antenna constants -#define ANT_TX TRSW //the tx line is transmitting -#define ANT_RX 0 //the tx line is receiving -#define ANT_TXRX 0 //the rx line is on txrx -#define ANT_RX2 LNASW //the rx line in on rx2 -#define ANT_XX LNASW //dont care how the antenna is set - -#include "adf4350_regs.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; -using namespace boost::assign; - -/*********************************************************************** - * The SBX dboard constants - **********************************************************************/ -static const freq_range_t sbx_freq_range(400e6, 4.4e9); - -static const freq_range_t sbx_tx_lo_2dbm = list_of - (range_t(0.35e9, 0.37e9)) -; - -static const freq_range_t sbx_enable_tx_lo_filter = list_of - (range_t(0.4e9, 1.5e9)) -; - -static const freq_range_t sbx_enable_rx_lo_filter = list_of - (range_t(0.4e9, 1.5e9)) -; - -static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); - -static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); - -static const uhd::dict sbx_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, double(0.5))) -; - -static const uhd::dict sbx_rx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, double(0.5))) -; - -/*********************************************************************** - * The SBX dboard - **********************************************************************/ -class sbx_xcvr : public xcvr_dboard_base{ -public: - sbx_xcvr(ctor_args_t args); - ~sbx_xcvr(void); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - -private: - uhd::dict _tx_gains, _rx_gains; - double _rx_lo_freq, _tx_lo_freq; - std::string _tx_ant, _rx_ant; - - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); - void set_rx_ant(const std::string &ant); - void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); - - void update_atr(void); - - /*! - * Set the LO frequency for the particular dboard unit. - * \param unit which unit rx or tx - * \param target_freq the desired frequency in Hz - * \return the actual frequency in Hz - */ - double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! - * Get the lock detect status of the LO. - * \param unit which unit rx or tx - * \return true for locked - */ - bool get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; - } - - /*! - * Flash the LEDs - */ - void flash_leds(void) { - //Remove LED gpios from ATR control temporarily and set to outputs - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - - /* - //flash All LEDs - for (int i = 0; i < 3; i++) { - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } - */ - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_TXRX|TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_RX1RX2|RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - /* - //flash All LEDs - for (int i = 0; i < 3; i++) { - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } - */ - //Put LED gpios back in ATR control and update atr - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - } - -}; - -/*********************************************************************** - * Register the SBX dboard (min freq, max freq, rx div2, tx div2) - **********************************************************************/ -static dboard_base::sptr make_sbx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new sbx_xcvr(args)); -} - -UHD_STATIC_BLOCK(reg_sbx_dboards){ - dboard_manager::register_dboard(0x0054, 0x0055, &make_sbx, "SBX"); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ - - //enable the clocks that we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - - //flash LEDs - flash_leds(); - - UHD_LOGV(often) << boost::format( - "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" - ) % RXIO_MASK % TXIO_MASK << std::endl; - - //set some default values - set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ - set_tx_gain(sbx_tx_gain_ranges[name].start(), name); - } - BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ - set_rx_gain(sbx_rx_gain_ranges[name].start(), name); - } -} - -sbx_xcvr::~sbx_xcvr(void){ - /* NOP */ -} - -/*********************************************************************** - * Gain Handling - **********************************************************************/ -static int rx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = sbx_rx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation and update iobits for atr - double attn = sbx_rx_gain_ranges["PGA0"].stop() - gain; - - //calculate the RX attenuation - int attn_code = int(floor(attn*2)); - int iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK; - - - UHD_LOGV(often) << boost::format( - "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = sbx_rx_gain_ranges["PGA0"].stop() - double(attn_code)/2; - - return iobits; -} - -static int tx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = sbx_tx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation and update iobits for atr - double attn = sbx_tx_gain_ranges["PGA0"].stop() - gain; - - //calculate the TX attenuation - int attn_code = int(floor(attn*2)); - int iobits = ((~attn_code) << TX_ATTN_SHIFT) & TX_ATTN_MASK; - - - UHD_LOGV(often) << boost::format( - "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = sbx_tx_gain_ranges["PGA0"].stop() - double(attn_code)/2; - - return iobits; -} - -void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ - assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); - if(name == "PGA0"){ - tx_pga0_gain_to_iobits(gain); - _tx_gains[name] = gain; - - //write the new gain to atr regs - update_atr(); - } - else UHD_THROW_INVALID_CODE_PATH(); -} - -void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ - assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); - if(name == "PGA0"){ - rx_pga0_gain_to_iobits(gain); - _rx_gains[name] = gain; - - //write the new gain to atr regs - update_atr(); - } - else UHD_THROW_INVALID_CODE_PATH(); -} - -/*********************************************************************** - * Antenna Handling - **********************************************************************/ -void sbx_xcvr::update_atr(void){ - //calculate atr pins - int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]); - int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); - int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; - int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; - int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; - int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; - int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; - int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; - - //setup the tx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_XX | TX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); - - //setup the rx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_ENB); - - //set the atr regs that change with antenna setting - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | TX_MIXER_DIS | - ((_rx_ant == "TX/RX")? ANT_RX : ANT_TX)); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | RX_MIXER_ENB | - ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)); - - UHD_LOGV(often) << boost::format( - "SBX RXONLY ATR REG: 0x%08x" - ) % (rx_pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl; -} - -void sbx_xcvr::set_rx_ant(const std::string &ant){ - //validate input - assert_has(sbx_rx_antennas, ant, "sbx rx antenna name"); - - //shadow the setting - _rx_ant = ant; - - //write the new antenna setting to atr regs - update_atr(); -} - -void sbx_xcvr::set_tx_ant(const std::string &ant){ - assert_has(sbx_tx_antennas, ant, "sbx tx antenna name"); - //only one antenna option, do nothing -} - -/*********************************************************************** - * Tuning - **********************************************************************/ -void sbx_xcvr::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void sbx_xcvr::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} - -double sbx_xcvr::set_lo_freq( - dboard_iface::unit_t unit, - double target_freq -){ - UHD_LOGV(often) << boost::format( - "SBX tune: target frequency %f Mhz" - ) % (target_freq/1e6) << std::endl; - - //clip the input - target_freq = sbx_freq_range.clip(target_freq); - - //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) - static const uhd::dict prescaler_to_min_int_div = map_list_of - (0,23) //adf4350_regs_t::PRESCALER_4_5 - (1,75) //adf4350_regs_t::PRESCALER_8_9 - ; - - //map rf divider select output dividers to enums - static const uhd::dict rfdivsel_to_enum = map_list_of - (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) - (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) - (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) - (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) - (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) - ; - - double actual_freq, pfd_freq; - double ref_freq = this->get_iface()->get_clock_rate(unit); - int R=0, BS=0, N=0, FRAC=0, MOD=0; - int RFdiv = 1; - adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; - adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; - - //Reference doubler for 50% duty cycle - // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 - if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; - - //increase RF divider until acceptable VCO frequency - //start with target_freq*2 because mixer has divide by 2 - double vco_freq = target_freq; - while (vco_freq < 2.2e9) { - vco_freq *= 2; - RFdiv *= 2; - } - - //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) - adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; - - /* - * The goal here is to loop though possible R dividers, - * band select clock dividers, N (int) dividers, and FRAC - * (frac) dividers. - * - * Calculate the N and F dividers for each set of values. - * The loop exists when it meets all of the constraints. - * The resulting loop values are loaded into the registers. - * - * from pg.21 - * - * f_pfd = f_ref*(1+D)/(R*(1+T)) - * f_vco = (N + (FRAC/MOD))*f_pfd - * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD - * f_rf = f_vco/RFdiv) - * f_actual = f_rf/2 - */ - for(R = 1; R <= 1023; R+=1){ - //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) - pfd_freq = ref_freq*(1+D)/(R*(1+T)); - - //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) - if (pfd_freq > 25e6) continue; - - //ignore fractional part of tuning - N = int(std::floor(vco_freq/pfd_freq)); - - //keep N > minimum int divider requirement - if (N < prescaler_to_min_int_div[prescaler]) continue; - - for(BS=1; BS <= 255; BS+=1){ - //keep the band select frequency at or below 100KHz - //constraint on band select clock - if (pfd_freq/BS > 100e3) continue; - goto done_loop; - } - } done_loop: - - //Fractional-N calculation - MOD = 4095; //max fractional accuracy - FRAC = int((vco_freq/pfd_freq - N)*MOD); - - //Reference divide-by-2 for 50% duty cycle - // if R even, move one divide by 2 to to regs.reference_divide_by_2 - if(R % 2 == 0){ - T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; - R /= 2; - } - - //actual frequency calculation - actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); - - UHD_LOGV(often) - << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % get_locked(unit)<< std::endl - << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" - ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; - - //load the register values - adf4350_regs_t regs; - - if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) - regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; - else - regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - regs.frac_12_bit = FRAC; - regs.int_16_bit = N; - regs.mod_12_bit = MOD; - regs.prescaler = prescaler; - regs.r_counter_10_bit = R; - regs.reference_divide_by_2 = T; - regs.reference_doubler = D; - regs.band_select_clock_div = BS; - UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); - regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; - - //write the registers - //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) - int addr; - - for(addr=5; addr>=0; addr--){ - UHD_LOGV(often) << boost::format( - "SBX SPI Reg (0x%02x): 0x%08x" - ) % addr % regs.get_reg(addr) << std::endl; - this->get_iface()->write_spi( - unit, spi_config_t::EDGE_RISE, - regs.get_reg(addr), 32 - ); - } - - //return the actual frequency - UHD_LOGV(often) << boost::format( - "SBX tune: actual frequency %f Mhz" - ) % (actual_freq/1e6) << std::endl; - return actual_freq; -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); - val = sbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); - val = sbx_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp new file mode 100644 index 000000000..51a0f0100 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_common.cpp @@ -0,0 +1,514 @@ +// +// Copyright 2011 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 "db_sbx_common.hpp" +#include "adf4350_regs.hpp" + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * Register the SBX dboard (min freq, max freq, rx div2, tx div2) + **********************************************************************/ +static dboard_base::sptr make_sbx(dboard_base::ctor_args_t args){ + return dboard_base::sptr(new sbx_xcvr(args)); +} + +UHD_STATIC_BLOCK(reg_sbx_dboards){ + dboard_manager::register_dboard(0x0054, 0x0055, &make_sbx, "SBX"); + dboard_manager::register_dboard(0x0065, 0x0064, &make_sbx, "SBX v4"); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +static int rx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = sbx_rx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation and update iobits for atr + double attn = sbx_rx_gain_ranges["PGA0"].stop() - gain; + + //calculate the RX attenuation + int attn_code = int(floor(attn*2)); + int iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = sbx_rx_gain_ranges["PGA0"].stop() - double(attn_code)/2; + + return iobits; +} + +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = sbx_tx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation and update iobits for atr + double attn = sbx_tx_gain_ranges["PGA0"].stop() - gain; + + //calculate the TX attenuation + int attn_code = int(floor(attn*2)); + int iobits = ((~attn_code) << TX_ATTN_SHIFT) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = sbx_tx_gain_ranges["PGA0"].stop() - double(attn_code)/2; + + return iobits; +} + +void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ + assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); + if(name == "PGA0"){ + tx_pga0_gain_to_iobits(gain); + _tx_gains[name] = gain; + + //write the new gain to atr regs + update_atr(); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + +void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ + assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); + if(name == "PGA0"){ + rx_pga0_gain_to_iobits(gain); + _rx_gains[name] = gain; + + //write the new gain to atr regs + update_atr(); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ + switch(get_rx_id().to_uint16()) { + case 0x054: + db_actual = sbx_versionx_sptr(new sbx_version3(this)); + break; + case 0x065: + db_actual = sbx_versionx_sptr(new sbx_version4(this)); + break; + default: + /* We didn't recognize the version of the board... */ + UHD_THROW_INVALID_CODE_PATH(); + } + + //enable the clocks that we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + + //flash LEDs + flash_leds(); + + UHD_LOGV(often) << boost::format( + "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" + ) % RXIO_MASK % TXIO_MASK << std::endl; + + //set some default values + set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + set_rx_ant("RX2"); + + BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ + set_tx_gain(sbx_tx_gain_ranges[name].start(), name); + } + BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ + set_rx_gain(sbx_rx_gain_ranges[name].start(), name); + } +} + +sbx_xcvr::~sbx_xcvr(void){ + /* NOP */ +} + +/*********************************************************************** + * Antenna Handling + **********************************************************************/ +void sbx_xcvr::update_atr(void){ + //calculate atr pins + int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]); + int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); + int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; + int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; + int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; + int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; + int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; + int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; + + //setup the tx atr (this does not change with antenna) + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_XX | TX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); + + //setup the rx atr (this does not change with antenna) + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_ENB); + + //set the atr regs that change with antenna setting + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | TX_MIXER_DIS | + ((_rx_ant == "TX/RX")? ANT_RX : ANT_TX)); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | RX_MIXER_ENB | + ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)); + + UHD_LOGV(often) << boost::format( + "SBX RXONLY ATR REG: 0x%08x" + ) % (rx_pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl; +} + +void sbx_xcvr::set_rx_ant(const std::string &ant){ + //validate input + assert_has(sbx_rx_antennas, ant, "sbx rx antenna name"); + + //shadow the setting + _rx_ant = ant; + + //write the new antenna setting to atr regs + update_atr(); +} + +void sbx_xcvr::set_tx_ant(const std::string &ant){ + assert_has(sbx_tx_antennas, ant, "sbx tx antenna name"); + //only one antenna option, do nothing +} + +/*********************************************************************** + * Tuning + **********************************************************************/ +void sbx_xcvr::set_rx_lo_freq(double freq){ + _rx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_RX, freq); +} + +void sbx_xcvr::set_tx_lo_freq(double freq){ + _tx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_TX, freq); +} + + +double sbx_xcvr::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + return db_actual->set_lo_freq(unit, target_freq); +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = get_rx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); + val = _rx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); + val = sbx_rx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(sbx_rx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _rx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = sbx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = _rx_ant; + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = sbx_rx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + this->set_rx_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_rx_gain(val.as(), key.name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_rx_ant(val.as()); + return; + + case SUBDEV_PROP_ENABLED: + return; //always enabled + + case SUBDEV_PROP_BANDWIDTH: + UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); + val = _tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); + val = sbx_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(sbx_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _tx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = sbx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string("TX/RX"); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = sbx_tx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_QI; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + this->set_tx_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_tx_gain(val.as(), key.name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_tx_ant(val.as()); + return; + + case SUBDEV_PROP_ENABLED: + return; //always enabled + + case SUBDEV_PROP_BANDWIDTH: + UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + + +bool sbx_xcvr::get_locked(dboard_iface::unit_t unit) { + return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +} + + +void sbx_xcvr::flash_leds(void) { + //Remove LED gpios from ATR control temporarily and set to outputs + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + + /* + //flash All LEDs + for (int i = 0; i < 3; i++) { + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + */ + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_TXRX|TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_RX1RX2|RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + /* + //flash All LEDs + for (int i = 0; i < 3; i++) { + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + */ + //Put LED gpios back in ATR control and update atr + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); +} + diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp new file mode 100644 index 000000000..5ff84811a --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_common.hpp @@ -0,0 +1,233 @@ +// +// Copyright 2011 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 . +// + + + +// Common IO Pins +#define LO_LPF_EN (1 << 15) +#define SYNTH_CE (1 << 3) +#define SYNTH_PDBRF (1 << 2) +#define SYNTH_MUXOUT (1 << 1) // INPUT!!! +#define LOCKDET_MASK (1 << 0) // INPUT!!! + +// TX IO Pins +#define TRSW (1 << 14) // 0 = TX, 1 = RX +#define TX_LED_TXRX (1 << 7) // LED for TX Antenna Selection TX/RX +#define TX_LED_LD (1 << 6) // LED for TX Lock Detect +#define DIS_POWER_TX (1 << 5) // on UNIT_TX, 0 powers up TX +#define TX_ENABLE (1 << 4) // on UNIT_TX, 0 disables TX Mixer + +// RX IO Pins +#define LNASW (1 << 14) // 0 = TX/RX, 1 = RX2 +#define RX_LED_RX1RX2 (1 << 7) // LED for RX Antenna Selection RX1/RX2 +#define RX_LED_LD (1 << 6) // LED for RX Lock Detect +#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX +#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband + +// RX Attenuator Pins +#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// TX Attenuator Pins +#define TX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define TX_ATTN_MASK (63 << TX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// Mixer functions +#define TX_MIXER_ENB (SYNTH_PDBRF) +#define TX_MIXER_DIS 0 + +#define RX_MIXER_ENB (SYNTH_PDBRF) +#define RX_MIXER_DIS 0 + +// Pin functions +#define TX_LED_IO (TX_LED_TXRX|TX_LED_LD) // LED gpio lines, pull down for LED +#define TXIO_MASK (LO_LPF_EN|TRSW|SYNTH_CE|SYNTH_PDBRF|TX_ATTN_MASK|DIS_POWER_TX|TX_ENABLE) + +#define RX_LED_IO (RX_LED_RX1RX2|RX_LED_LD) // LED gpio lines, pull down for LED +#define RXIO_MASK (LO_LPF_EN|LNASW|SYNTH_CE|SYNTH_PDBRF|RX_ATTN_MASK|DIS_POWER_RX|RX_DISABLE) + +// Power functions +#define TX_POWER_UP (SYNTH_CE|TX_ENABLE) +#define TX_POWER_DOWN (DIS_POWER_TX) + +#define RX_POWER_UP (SYNTH_CE) +#define RX_POWER_DOWN (DIS_POWER_RX) + +// Antenna constants +#define ANT_TX TRSW //the tx line is transmitting +#define ANT_RX 0 //the tx line is receiving +#define ANT_TXRX 0 //the rx line is on txrx +#define ANT_RX2 LNASW //the rx line in on rx2 +#define ANT_XX LNASW //dont care how the antenna is set + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * The SBX dboard constants + **********************************************************************/ +static const freq_range_t sbx_freq_range(400e6, 4.4e9); + +static const freq_range_t sbx_tx_lo_2dbm = list_of + (range_t(0.35e9, 0.37e9)) +; + +static const freq_range_t sbx_enable_tx_lo_filter = list_of + (range_t(0.4e9, 1.5e9)) +; + +static const freq_range_t sbx_enable_rx_lo_filter = list_of + (range_t(0.4e9, 1.5e9)) +; + +static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); + +static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); + +static const uhd::dict sbx_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31.5, double(0.5))) +; + +static const uhd::dict sbx_rx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31.5, double(0.5))) +; + +/*********************************************************************** + * The SBX dboard + **********************************************************************/ +class sbx_xcvr : public xcvr_dboard_base{ +public: + sbx_xcvr(ctor_args_t args); + ~sbx_xcvr(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +protected: + + uhd::dict _tx_gains, _rx_gains; + double _rx_lo_freq, _tx_lo_freq; + std::string _tx_ant, _rx_ant; + + void set_rx_lo_freq(double freq); + void set_tx_lo_freq(double freq); + void set_rx_ant(const std::string &ant); + void set_tx_ant(const std::string &ant); + void set_rx_gain(double gain, const std::string &name); + void set_tx_gain(double gain, const std::string &name); + + void update_atr(void); + + /*! + * Set the LO frequency for the particular dboard unit. + * \param unit which unit rx or tx + * \param target_freq the desired frequency in Hz + * \return the actual frequency in Hz + */ + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! + * Get the lock detect status of the LO. + * \param unit which unit rx or tx + * \return true for locked + */ + bool get_locked(dboard_iface::unit_t unit); + + /*! + * Flash the LEDs + */ + void flash_leds(void); + + /*! + * Version-agnostic ABC that wraps version-specific implementations of the + * WBX base daughterboard. + * + * This class is an abstract base class, and thus is impossible to + * instantiate. + */ + class sbx_versionx { + public: + sbx_versionx() {} + ~sbx_versionx(void) {} + + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + }; + + /*! + * Version 3 of the SBX Daughterboard + */ + class sbx_version3 : public sbx_versionx { + public: + sbx_version3(sbx_xcvr *_self_sbx_xcvr); + ~sbx_version3(void); + + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, sbx_base. */ + sbx_xcvr *self_base; + }; + + /*! + * Version 4 of the SBX Daughterboard + * + * The only difference in the fourth revision is the ADF4351 vs the ADF4350. + */ + class sbx_version4 : public sbx_versionx { + public: + sbx_version4(sbx_xcvr *_self_sbx_xcvr); + ~sbx_version4(void); + + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, sbx_base. */ + sbx_xcvr *self_base; + }; + + /*! + * Handle to the version-specific implementation of the SBX. + * + * Since many of this class's functions are dependent on the version of the + * SBX board, this class will instantiate an object of the appropriate + * sbx_version* subclass, and invoke any relevant functions through that + * object. This pointer is set to the proper object at construction time. + */ + typedef boost::shared_ptr sbx_versionx_sptr; + sbx_versionx_sptr db_actual; +}; + diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp new file mode 100644 index 000000000..b5aad8aa5 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -0,0 +1,186 @@ +// +// Copyright 2011 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 "adf4350_regs.hpp" +#include "db_sbx_common.hpp" + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_version3::sbx_version3(sbx_xcvr *_self_sbx_xcvr) { + //register the handle to our base SBX class + self_base = _self_sbx_xcvr; +} + +sbx_xcvr::sbx_version3::~sbx_version3(void){ + /* NOP */ +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "SBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //clip the input + target_freq = sbx_freq_range.clip(target_freq); + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); + + UHD_LOGV(often) + << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) + regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + else + regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "SBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "SBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp new file mode 100644 index 000000000..ea0acb699 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -0,0 +1,189 @@ +// +// Copyright 2011 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 "adf4351_regs.hpp" +#include "db_sbx_common.hpp" + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_version4::sbx_version4(sbx_xcvr *_self_sbx_xcvr) { + //register the handle to our base SBX class + self_base = _self_sbx_xcvr; +} + + +sbx_xcvr::sbx_version4::~sbx_version4(void){ + /* NOP */ +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "SBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //clip the input + target_freq = sbx_freq_range.clip(target_freq); + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4351_regs_t::PRESCALER_4_5 + (1,75) //adf4351_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4351_regs_t::reference_divide_by_2_t T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4351_regs_t::reference_doubler_t D = adf4351_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4351_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); + + UHD_LOGV(often) + << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4351_regs_t regs; + + if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) + regs.output_power = adf4351_regs_t::OUTPUT_POWER_2DBM; + else + regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "SBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "SBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + -- cgit v1.2.3 From aa0513375eb60a594f323b82d6f06c7b69c574fc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 12:58:43 -0700 Subject: wbx: squashed Ben's WBX work --- host/lib/ic_reg_maps/gen_adf4350_regs.py | 1 + host/lib/usrp/dboard/CMakeLists.txt | 3 + host/lib/usrp/dboard/db_wbx_common.cpp | 486 +++---------------------------- host/lib/usrp/dboard/db_wbx_common.hpp | 172 ++++++++++- host/lib/usrp/dboard/db_wbx_simple.cpp | 47 ++- host/lib/usrp/dboard/db_wbx_version2.cpp | 394 +++++++++++++++++++++++++ host/lib/usrp/dboard/db_wbx_version3.cpp | 401 +++++++++++++++++++++++++ host/lib/usrp/dboard/db_wbx_version4.cpp | 404 +++++++++++++++++++++++++ 8 files changed, 1447 insertions(+), 461 deletions(-) create mode 100644 host/lib/usrp/dboard/db_wbx_version2.cpp create mode 100644 host/lib/usrp/dboard/db_wbx_version3.cpp create mode 100644 host/lib/usrp/dboard/db_wbx_version4.cpp (limited to 'host/lib/usrp') diff --git a/host/lib/ic_reg_maps/gen_adf4350_regs.py b/host/lib/ic_reg_maps/gen_adf4350_regs.py index bccdb2edf..fce2f569b 100755 --- a/host/lib/ic_reg_maps/gen_adf4350_regs.py +++ b/host/lib/ic_reg_maps/gen_adf4350_regs.py @@ -51,6 +51,7 @@ reference_divide_by_2 2[24] 1 disabled, enabled reference_doubler 2[25] 0 disabled, enabled muxout 2[26:28] 1 3state, dvdd, dgnd, rdiv, ndiv, analog_ld, dld, reserved low_noise_and_spur 2[29:30] 3 low_noise, reserved0, reserved1, low_spur +##reserved 2[31] 0 ######################################################################## ## address 3 ######################################################################## diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index a865a7858..744285ac3 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -27,6 +27,9 @@ LIBUHD_APPEND_SOURCES( #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index c7f8ba55d..63f70e3d5 100644 --- a/host/lib/usrp/dboard/db_wbx_common.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -15,151 +15,22 @@ // along with this program. If not, see . // -// Common IO Pins -#define ADF4350_CE (1 << 3) -#define ADF4350_PDBRF (1 << 2) -#define ADF4350_MUXOUT (1 << 1) // INPUT!!! -#define LOCKDET_MASK (1 << 0) // INPUT!!! - -// TX IO Pins -#define TX_PUP_5V (1 << 7) // enables 5.0V power supply -#define TX_PUP_3V (1 << 6) // enables 3.3V supply -#define TXMOD_EN (1 << 4) // on UNIT_TX, 1 enables TX Modulator - -// RX IO Pins -#define RX_PUP_5V (1 << 7) // enables 5.0V power supply -#define RX_PUP_3V (1 << 6) // enables 3.3V supply -#define RXBB_PDB (1 << 4) // on UNIT_RX, 1 powers up RX baseband - -// RX Attenuator Pins -#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// TX Attenuator Pins (v3 only) -#define TX_ATTN_16 (1 << 14) -#define TX_ATTN_8 (1 << 5) -#define TX_ATTN_4 (1 << 4) -#define TX_ATTN_2 (1 << 3) -#define TX_ATTN_1 (1 << 1) -#define TX_ATTN_MASK (TX_ATTN_16|TX_ATTN_8|TX_ATTN_4|TX_ATTN_2|TX_ATTN_1) // valid bits of TX Attenuator Control - -// Mixer functions -#define TX_MIXER_ENB (TXMOD_EN|ADF4350_PDBRF) // for v3, TXMOD_EN tied to ADF4350_PDBRF rather than separate -#define TX_MIXER_DIS 0 - -#define RX_MIXER_ENB (RXBB_PDB|ADF4350_PDBRF) -#define RX_MIXER_DIS 0 - -// Power functions -#define TX_POWER_UP (TX_PUP_5V|TX_PUP_3V) // high enables power supply -#define TX_POWER_DOWN 0 - -#define RX_POWER_UP (RX_PUP_5V|RX_PUP_3V|ADF4350_CE) // high enables power supply -#define RX_POWER_DOWN 0 - #include "db_wbx_common.hpp" #include "adf4350_regs.hpp" -#include #include #include #include #include #include #include -#include -#include -#include -#include using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; -/*********************************************************************** - * The WBX Common dboard constants - **********************************************************************/ -static const uhd::dict wbx_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 25, 0.05)) -; - -static const uhd::dict wbx_v3_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31, 1.0)) -; - -static const uhd::dict wbx_rx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, 0.5)) -; - -/*********************************************************************** - * WBX Common Implementation - **********************************************************************/ -wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ - - //enable the clocks that we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //v3 has different io bits for attenuator control - int v3_iobits = is_v3() ? TX_ATTN_MASK : ADF4350_CE; - int v3_tx_mod = is_v3() ? ADF4350_PDBRF : TXMOD_EN|ADF4350_PDBRF; - - //set the gpio directions and atr controls - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v3_tx_mod); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v3_tx_mod|v3_iobits); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); - - //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - if (is_v3()) { - BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ - set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); - } - } - else { - BOOST_FOREACH(const std::string &name, wbx_tx_gain_ranges.keys()){ - set_tx_gain(wbx_tx_gain_ranges[name].start(), name); - } - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - set_rx_enabled(false); - set_tx_enabled(false); -} - -wbx_base::~wbx_base(void){ - /* NOP */ -} - -/*********************************************************************** - * Enables - **********************************************************************/ -void wbx_base::set_rx_enabled(bool enb){ - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, - (enb)? RX_POWER_UP : RX_POWER_DOWN, RX_POWER_UP | RX_POWER_DOWN - ); -} - -void wbx_base::set_tx_enabled(bool enb){ - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, - (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | (is_v3() ? 0 : ADF4350_CE) - ); -} /*********************************************************************** - * Gain Handling + * Gain-related functions **********************************************************************/ static int rx_pga0_gain_to_iobits(double &gain){ //clip the input @@ -182,79 +53,50 @@ static int rx_pga0_gain_to_iobits(double &gain){ return iobits; } -//v3 TX gains -static int tx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = wbx_v3_tx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation - double attn = wbx_v3_tx_gain_ranges["PGA0"].stop() - gain; - //calculate the attenuation - int attn_code = boost::math::iround(attn); - int iobits = ( - (attn_code & 16 ? 0 : TX_ATTN_16) | - (attn_code & 8 ? 0 : TX_ATTN_8) | - (attn_code & 4 ? 0 : TX_ATTN_4) | - (attn_code & 2 ? 0 : TX_ATTN_2) | - (attn_code & 1 ? 0 : TX_ATTN_1) - ) & TX_ATTN_MASK; - - UHD_LOGV(often) << boost::format( - "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = wbx_v3_tx_gain_ranges["PGA0"].stop() - double(attn_code); - - return iobits; +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ + switch(get_rx_id().to_uint16()) { + case 0x053: + db_actual = wbx_versionx_sptr(new wbx_version2(this)); + return; + case 0x057: + db_actual = wbx_versionx_sptr(new wbx_version3(this)); + return; + case 0x063: + db_actual = wbx_versionx_sptr(new wbx_version4(this)); + return; + default: + /* We didn't recognize the version of the board... */ + UHD_THROW_INVALID_CODE_PATH(); + } } -//Pre v3 TX gains -static double tx_pga0_gain_to_dac_volts(double &gain){ - //clip the input - gain = wbx_tx_gain_ranges["PGA0"].clip(gain); - - //voltage level constants - static const double max_volts = 0.5, min_volts = 1.4; - static const double slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].stop(); - - //calculate the voltage for the aux dac - double dac_volts = gain*slope + min_volts; - UHD_LOGV(often) << boost::format( - "WBX TX Gain: %f dB, dac_volts: %f V" - ) % gain % dac_volts << std::endl; +wbx_base::~wbx_base(void){ + /* NOP */ +} - //the actual gain setting - gain = (dac_volts - min_volts)/slope; +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::set_rx_enabled(bool enb){ + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, + (enb)? RX_POWER_UP : RX_POWER_DOWN, RX_POWER_UP | RX_POWER_DOWN + ); +} - return dac_volts; +void wbx_base::set_tx_enabled(bool enb){ + db_actual->set_tx_enabled(enb); } +/*********************************************************************** + * Gain Handling + **********************************************************************/ void wbx_base::set_tx_gain(double gain, const std::string &name){ - if (is_v3()) { - assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); - if(name == "PGA0"){ - boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); - _tx_gains[name] = gain; - - //write the new gain to tx gpio outputs - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); - } - else UHD_THROW_INVALID_CODE_PATH(); - } - else { - assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name"); - if(name == "PGA0"){ - double dac_volts = tx_pga0_gain_to_dac_volts(gain); - _tx_gains[name] = gain; - - //write the new voltage to the aux dac - this->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); - } - else UHD_THROW_INVALID_CODE_PATH(); - } + db_actual->set_tx_gain(gain, name); } void wbx_base::set_rx_gain(double gain, const std::string &name){ @@ -272,183 +114,18 @@ void wbx_base::set_rx_gain(double gain, const std::string &name){ /*********************************************************************** * Tuning **********************************************************************/ -double wbx_base::set_lo_freq( - dboard_iface::unit_t unit, - double target_freq -){ - UHD_LOGV(often) << boost::format( - "WBX tune: target frequency %f Mhz" - ) % (target_freq/1e6) << std::endl; - - //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) - static const uhd::dict prescaler_to_min_int_div = map_list_of - (0,23) //adf4350_regs_t::PRESCALER_4_5 - (1,75) //adf4350_regs_t::PRESCALER_8_9 - ; - - //map rf divider select output dividers to enums - static const uhd::dict rfdivsel_to_enum = map_list_of - (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) - (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) - (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) - (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) - (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) - ; - - double actual_freq, pfd_freq; - double ref_freq = this->get_iface()->get_clock_rate(unit); - int R=0, BS=0, N=0, FRAC=0, MOD=0; - int RFdiv = 1; - adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; - adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; - - //Reference doubler for 50% duty cycle - // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 - if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; - - //increase RF divider until acceptable VCO frequency - //start with target_freq*2 because mixer has divide by 2 - double vco_freq = target_freq*2; - while (vco_freq < 2.2e9) { - vco_freq *= 2; - RFdiv *= 2; - } - - //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) - adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; - - /* - * The goal here is to loop though possible R dividers, - * band select clock dividers, N (int) dividers, and FRAC - * (frac) dividers. - * - * Calculate the N and F dividers for each set of values. - * The loop exists when it meets all of the constraints. - * The resulting loop values are loaded into the registers. - * - * from pg.21 - * - * f_pfd = f_ref*(1+D)/(R*(1+T)) - * f_vco = (N + (FRAC/MOD))*f_pfd - * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD - * f_rf = f_vco/RFdiv) - * f_actual = f_rf/2 - */ - for(R = 1; R <= 1023; R+=1){ - //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) - pfd_freq = ref_freq*(1+D)/(R*(1+T)); - - //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) - if (pfd_freq > 25e6) continue; - - //ignore fractional part of tuning - N = int(std::floor(vco_freq/pfd_freq)); - - //keep N > minimum int divider requirement - if (N < prescaler_to_min_int_div[prescaler]) continue; - - for(BS=1; BS <= 255; BS+=1){ - //keep the band select frequency at or below 100KHz - //constraint on band select clock - if (pfd_freq/BS > 100e3) continue; - goto done_loop; - } - } done_loop: - - //Fractional-N calculation - MOD = 4095; //max fractional accuracy - FRAC = int((vco_freq/pfd_freq - N)*MOD); - - //Reference divide-by-2 for 50% duty cycle - // if R even, move one divide by 2 to to regs.reference_divide_by_2 - if(R % 2 == 0){ - T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; - R /= 2; - } - - //actual frequency calculation - actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); - - - UHD_LOGV(often) - << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % get_locked(unit)<< std::endl - << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" - ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; - - //load the register values - adf4350_regs_t regs; - - regs.frac_12_bit = FRAC; - regs.int_16_bit = N; - regs.mod_12_bit = MOD; - regs.prescaler = prescaler; - regs.r_counter_10_bit = R; - regs.reference_divide_by_2 = T; - regs.reference_doubler = D; - regs.band_select_clock_div = BS; - UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); - regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; - - if (unit == dboard_iface::UNIT_RX) { - freq_range_t rx_lo_5dbm = list_of - (range_t(0.05e9, 1.4e9)) - ; - - freq_range_t rx_lo_2dbm = list_of - (range_t(1.4e9, 2.2e9)) - ; - - if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; - - } else if (unit == dboard_iface::UNIT_TX) { - freq_range_t tx_lo_5dbm = list_of - (range_t(0.05e9, 1.7e9)) - (range_t(1.9e9, 2.2e9)) - ; - - freq_range_t tx_lo_m1dbm = list_of - (range_t(1.7e9, 1.9e9)) - ; - - if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; - - } - - //write the registers - //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) - int addr; - - for(addr=5; addr>=0; addr--){ - UHD_LOGV(often) << boost::format( - "WBX SPI Reg (0x%02x): 0x%08x" - ) % addr % regs.get_reg(addr) << std::endl; - this->get_iface()->write_spi( - unit, spi_config_t::EDGE_RISE, - regs.get_reg(addr), 32 - ); - } +freq_range_t wbx_base::get_freq_range(void) { + return db_actual->get_freq_range(); +} - //return the actual frequency - UHD_LOGV(often) << boost::format( - "WBX tune: actual frequency %f Mhz" - ) % (actual_freq/1e6) << std::endl; - return actual_freq; +double wbx_base::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + return db_actual->set_lo_freq(unit, target_freq); } bool wbx_base::get_locked(dboard_iface::unit_t unit){ return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; } -bool wbx_base::is_v3(void){ - return get_rx_id().to_uint16() == 0x057; -} /*********************************************************************** * RX Get and Set @@ -552,84 +229,7 @@ void wbx_base::rx_set(const wax::obj &key_, const wax::obj &val){ * TX Get and Set **********************************************************************/ void wbx_base::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "wbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - if (is_v3()) { - assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v3_tx_gain_ranges[key.name]; - } - else { - assert_has(wbx_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_tx_gain_ranges[key.name]; - } - return; - - case SUBDEV_PROP_GAIN_NAMES: - if (is_v3()) - val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); - else - val = prop_names_t(wbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = _tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + db_actual->tx_get(key_, val); } void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ @@ -654,3 +254,5 @@ void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ default: UHD_THROW_PROP_SET_ERROR(); } } + + diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 5d33ddce9..57e2a0fe6 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -18,14 +18,74 @@ #ifndef INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP #define INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP -#include "adf4350_regs.hpp" +// Common IO Pins +#define ADF4350_CE (1 << 3) +#define ADF4350_PDBRF (1 << 2) +#define ADF4350_MUXOUT (1 << 1) // INPUT!!! +#define ADF4351_CE (1 << 3) +#define ADF4351_PDBRF (1 << 2) +#define ADF4351_MUXOUT (1 << 1) // INPUT!!! + +#define LOCKDET_MASK (1 << 0) // INPUT!!! + +// TX IO Pins +#define TX_PUP_5V (1 << 7) // enables 5.0V power supply +#define TX_PUP_3V (1 << 6) // enables 3.3V supply +#define TXMOD_EN (1 << 4) // on UNIT_TX, 1 enables TX Modulator + +// RX IO Pins +#define RX_PUP_5V (1 << 7) // enables 5.0V power supply +#define RX_PUP_3V (1 << 6) // enables 3.3V supply +#define RXBB_PDB (1 << 4) // on UNIT_RX, 1 powers up RX baseband + +// RX Attenuator Pins +#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// TX Attenuator Pins (v3 only) +#define TX_ATTN_16 (1 << 14) +#define TX_ATTN_8 (1 << 5) +#define TX_ATTN_4 (1 << 4) +#define TX_ATTN_2 (1 << 3) +#define TX_ATTN_1 (1 << 1) +#define TX_ATTN_MASK (TX_ATTN_16|TX_ATTN_8|TX_ATTN_4|TX_ATTN_2|TX_ATTN_1) // valid bits of TX Attenuator Control + +// Mixer functions +#define TX_MIXER_ENB (TXMOD_EN|ADF4350_PDBRF) // for v3, TXMOD_EN tied to ADF4350_PDBRF rather than separate +#define TX_MIXER_DIS 0 + +#define RX_MIXER_ENB (RXBB_PDB|ADF4350_PDBRF) +#define RX_MIXER_DIS 0 + +// Power functions +#define TX_POWER_UP (TX_PUP_5V|TX_PUP_3V) // high enables power supply +#define TX_POWER_DOWN 0 + +#define RX_POWER_UP (RX_PUP_5V|RX_PUP_3V|ADF4350_CE) // high enables power supply +#define RX_POWER_DOWN 0 + + #include #include +#include #include +#include #include +#include +#include +#include +#include namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The WBX Common dboard constants + **********************************************************************/ +static const uhd::dict wbx_rx_gain_ranges = boost::assign::map_list_of + ("PGA0", gain_range_t(0, 31.5, 0.5)); + + /*********************************************************************** * The WBX dboard base class **********************************************************************/ @@ -41,11 +101,17 @@ protected: virtual void set_rx_enabled(bool enb); virtual void set_tx_enabled(bool enb); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); + virtual void rx_get(const wax::obj &key, wax::obj &val); + virtual void rx_set(const wax::obj &key, const wax::obj &val); - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); + virtual void tx_get(const wax::obj &key, wax::obj &val); + virtual void tx_set(const wax::obj &key, const wax::obj &val); + + /*! + * Retrieve the frequency range of the board. + * \return the frequency range as a freq_range_t + */ + virtual freq_range_t get_freq_range(void); /*! * Set the LO frequency for the particular dboard unit. @@ -57,22 +123,110 @@ protected: /*! * Get the lock detect status of the LO. + * + * This operation is identical for all versions of the WBX board. * \param unit which unit rx or tx * \return true for locked */ virtual bool get_locked(dboard_iface::unit_t unit); + /*! - * Detect if this a v3 WBX - * \return true for locked + * Version-agnostic ABC that wraps version-specific implementations of the + * WBX base daughterboard. + * + * This class is an abstract base class, and thus is impossible to + * instantiate. */ - virtual bool is_v3(void); + class wbx_versionx { + public: + wbx_versionx() {} + ~wbx_versionx(void) {} + + virtual void set_tx_gain(double gain, const std::string &name) = 0; + virtual void set_tx_enabled(bool enb) = 0; + virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; + virtual freq_range_t get_freq_range(void) = 0; + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + }; + + + /*! + * Version 2 of the WBX Daughterboard + * + * Basically the original release of the DB. + */ + class wbx_version2 : public wbx_versionx { + public: + wbx_version2(wbx_base *_self_wbx_base); + ~wbx_version2(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Version 3 of the WBX Daughterboard + * + * Fixed a problem with the AGC from Version 2. + */ + class wbx_version3 : public wbx_versionx { + public: + wbx_version3(wbx_base *_self_wbx_base); + ~wbx_version3(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Version 4 of the WBX Daughterboard + * + * Upgrades the Frequnecy Synthensizer from ADF4350 to ADF4351. + */ + class wbx_version4 : public wbx_versionx { + public: + wbx_version4(wbx_base *_self_wbx_base); + ~wbx_version4(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Handle to the version-specific implementation of the WBX. + * + * Since many of this class's functions are dependent on the version of the + * WBX board, this class will instantiate an object of the appropriate + * wbx_version_* subclass, and invoke any relevant functions through that + * object. This pointer is set to the proper object at construction time. + */ + typedef boost::shared_ptr wbx_versionx_sptr; + wbx_versionx_sptr db_actual; -private: uhd::dict _tx_gains, _rx_gains; bool _rx_enabled, _tx_enabled; }; + }} //namespace uhd::usrp #endif /* INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP */ diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 990bacbc8..789146854 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -32,15 +32,17 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; + /*********************************************************************** * The WBX Simple dboard constants **********************************************************************/ -static const freq_range_t wbx_freq_range(68.75e6, 2.2e9); - static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); +//this will get set by a version-specific function call +static freq_range_t wbx_freq_range(0.0, 0.0); + /*********************************************************************** * The WBX simple implementation **********************************************************************/ @@ -72,13 +74,19 @@ static dboard_base::sptr make_wbx_simple(dboard_base::ctor_args_t args){ return dboard_base::sptr(new wbx_simple(args)); } +/*********************************************************************** + * ID Numbers for WBX daughterboard combinations. + **********************************************************************/ UHD_STATIC_BLOCK(reg_wbx_simple_dboards){ dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx_simple, "WBX"); dboard_manager::register_dboard(0x0053, 0x004f, &make_wbx_simple, "WBX + Simple GDB"); dboard_manager::register_dboard(0x0057, 0x0056, &make_wbx_simple, "WBX v3"); dboard_manager::register_dboard(0x0057, 0x004f, &make_wbx_simple, "WBX v3 + Simple GDB"); + dboard_manager::register_dboard(0x0063, 0x0062, &make_wbx_simple, "WBX v4"); + dboard_manager::register_dboard(0x0063, 0x004f, &make_wbx_simple, "WBX v4 + Simple GDB"); } + /*********************************************************************** * Structors **********************************************************************/ @@ -100,6 +108,9 @@ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ANT_RX2, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_RX2, ANTSW_IO); + //get the frequency range of our WBX db + wbx_freq_range = this->get_freq_range(); + //set some default values set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); @@ -149,11 +160,19 @@ void wbx_simple::rx_get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case SUBDEV_PROP_NAME: - if (is_v3()) - val = std::string("WBX v3 RX + Simple GDB"); - else + switch(get_rx_id().to_uint16()) { + case 0x053: val = std::string("WBX RX + Simple GDB"); - return; + return; + case 0x057: + val = std::string("WBX v3 RX + Simple GDB"); + return; + case 0x063: + val = std::string("WBX v4 RX + Simple GDB"); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); + } case SUBDEV_PROP_FREQ: val = _rx_lo_freq; @@ -206,11 +225,19 @@ void wbx_simple::tx_get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case SUBDEV_PROP_NAME: - if (is_v3()) - val = std::string("WBX v3 TX + Simple GDB"); - else + switch(get_rx_id().to_uint16()) { + case 0x053: val = std::string("WBX TX + Simple GDB"); - return; + return; + case 0x057: + val = std::string("WBX v3 TX + Simple GDB"); + return; + case 0x063: + val = std::string("WBX v4 TX + Simple GDB"); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); + } case SUBDEV_PROP_FREQ: val = _tx_lo_freq; diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp new file mode 100644 index 000000000..0b57a6e2d --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -0,0 +1,394 @@ +// +// Copyright 2011 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 "db_wbx_common.hpp" +#include "adf4350_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 2 Constants + **********************************************************************/ +static const uhd::dict wbx_v2_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 25, 0.05)) +; + +static const freq_range_t wbx_v2_freq_range(68.75e6, 2.2e9); + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static double tx_pga0_gain_to_dac_volts(double &gain){ + //clip the input + gain = wbx_v2_tx_gain_ranges["PGA0"].clip(gain); + + //voltage level constants + static const double max_volts = 0.5, min_volts = 1.4; + static const double slope = (max_volts-min_volts)/wbx_v2_tx_gain_ranges["PGA0"].stop(); + + //calculate the voltage for the aux dac + double dac_volts = gain*slope + min_volts; + + UHD_LOGV(often) << boost::format( + "WBX TX Gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; + + return dac_volts; +} + + +/*********************************************************************** + * WBX Version 2 Implementation + **********************************************************************/ +wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v2_iobits = ADF4350_CE; + int v2_tx_mod = TXMOD_EN|ADF4350_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v2_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v2_tx_mod|v2_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()) { + set_tx_gain(wbx_v2_tx_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()) { + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version2::~wbx_version2(void){ + /* NOP */ +} + +/*********************************************************************** + * Enables + **********************************************************************/ + +void wbx_base::wbx_version2::set_tx_enabled(bool enb){ + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | ADF4350_CE); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ + assert_has(wbx_v2_tx_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + double dac_volts = tx_pga0_gain_to_dac_volts(gain); + self_base->_tx_gains[name] = gain; + + //write the new voltage to the aux dac + self_base->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version2::get_freq_range(void) { + return wbx_v2_freq_range; +} + +double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version2::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v2_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v2_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v2_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp new file mode 100644 index 000000000..3c5cdf5ba --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -0,0 +1,401 @@ +// +// Copyright 2011 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 "db_wbx_common.hpp" +#include "adf4350_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 3 Constants + **********************************************************************/ +static const uhd::dict wbx_v3_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31, 1.0)) +; + +static const freq_range_t wbx_v3_freq_range(68.75e6, 2.2e9); + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = wbx_v3_tx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation + double attn = wbx_v3_tx_gain_ranges["PGA0"].stop() - gain; + + //calculate the attenuation + int attn_code = boost::math::iround(attn); + int iobits = ( + (attn_code & 16 ? 0 : TX_ATTN_16) | + (attn_code & 8 ? 0 : TX_ATTN_8) | + (attn_code & 4 ? 0 : TX_ATTN_4) | + (attn_code & 2 ? 0 : TX_ATTN_2) | + (attn_code & 1 ? 0 : TX_ATTN_1) + ) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = wbx_v3_tx_gain_ranges["PGA0"].stop() - double(attn_code); + + return iobits; +} + + +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v3_iobits = TX_ATTN_MASK; + int v3_tx_mod = ADF4350_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v3_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v3_tx_mod|v3_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + //set some default values + BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ + set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version3::~wbx_version3(void){ + /* NOP */ +} + + +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::wbx_version3::set_tx_enabled(bool enb){ + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | 0); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ + assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); + self_base->_tx_gains[name] = gain; + + //write the new gain to tx gpio outputs + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version3::get_freq_range(void) { + return wbx_v3_freq_range; +} + +double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version3::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v3_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp new file mode 100644 index 000000000..b5104c9f1 --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -0,0 +1,404 @@ +// +// Copyright 2011 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 "db_wbx_common.hpp" +#include "adf4351_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 3 Constants + **********************************************************************/ +static const uhd::dict wbx_v4_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31, 1.0)) +; + +static const freq_range_t wbx_v4_freq_range(50.0e6, 2.2e9); + + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = wbx_v4_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation + double attn = wbx_v4_gain_ranges["PGA0"].stop() - gain; + + //calculate the attenuation + int attn_code = boost::math::iround(attn); + int iobits = ( + (attn_code & 16 ? 0 : TX_ATTN_16) | + (attn_code & 8 ? 0 : TX_ATTN_8) | + (attn_code & 4 ? 0 : TX_ATTN_4) | + (attn_code & 2 ? 0 : TX_ATTN_2) | + (attn_code & 1 ? 0 : TX_ATTN_1) + ) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = wbx_v4_gain_ranges["PGA0"].stop() - double(attn_code); + + return iobits; +} + + +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v4_iobits = TX_ATTN_MASK; + int v4_tx_mod = ADF4351_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v4_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4351_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v4_tx_mod|v4_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4351_CE|RXBB_PDB|ADF4351_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + //set some default values + BOOST_FOREACH(const std::string &name, wbx_v4_gain_ranges.keys()){ + set_tx_gain(wbx_v4_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version4::~wbx_version4(void){ + /* NOP */ +} + + +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::wbx_version4::set_tx_enabled(bool enb) { + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4351_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | 0); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { + assert_has(wbx_v4_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); + self_base->_tx_gains[name] = gain; + + //write the new gain to tx gpio outputs + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version4::get_freq_range(void) { + return wbx_v4_freq_range; +} + +double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4351_regs_t::PRESCALER_4_5 + (1,75) //adf4351_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV32) + (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4351_regs_t::reference_divide_by_2_t T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4351_regs_t::reference_doubler_t D = adf4351_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4351_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exits when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4351_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version4::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v4_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v4_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v4_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + -- cgit v1.2.3 From 8e398397ed55ae4df014902352c66429fda2e2c0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 13:15:44 -0700 Subject: sbx: bring SBX into the tree --- host/lib/usrp/dboard/CMakeLists.txt | 6 +- host/lib/usrp/dboard/db_sbx_common.cpp | 295 +++++++------------------------ host/lib/usrp/dboard/db_sbx_common.hpp | 16 +- host/lib/usrp/dboard/db_sbx_version3.cpp | 4 +- host/lib/usrp/dboard/db_sbx_version4.cpp | 4 +- 5 files changed, 79 insertions(+), 246 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 744285ac3..50662a96e 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -23,9 +23,9 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp index 51a0f0100..27b930f81 100644 --- a/host/lib/usrp/dboard/db_sbx_common.cpp +++ b/host/lib/usrp/dboard/db_sbx_common.cpp @@ -81,7 +81,7 @@ static int tx_pga0_gain_to_iobits(double &gain){ return iobits; } -void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ +double sbx_xcvr::set_tx_gain(double gain, const std::string &name){ assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); if(name == "PGA0"){ tx_pga0_gain_to_iobits(gain); @@ -91,9 +91,10 @@ void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ update_atr(); } else UHD_THROW_INVALID_CODE_PATH(); + return _tx_gains[name]; } -void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ +double sbx_xcvr::set_rx_gain(double gain, const std::string &name){ assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); if(name == "PGA0"){ rx_pga0_gain_to_iobits(gain); @@ -103,6 +104,7 @@ void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ update_atr(); } else UHD_THROW_INVALID_CODE_PATH(); + return _rx_gains[name]; } @@ -122,6 +124,64 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ UHD_THROW_INVALID_CODE_PATH(); } + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("SBX RX"); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&sbx_xcvr::get_locked, this, dboard_iface::UNIT_RX)); + BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&sbx_xcvr::set_rx_gain, this, _1, name)) + .set(sbx_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(sbx_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&sbx_xcvr::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(sbx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&sbx_xcvr::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(sbx_rx_antennas); + this->get_rx_subtree()->create("connection").set("IQ"); + this->get_rx_subtree()->create("enabled").set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("SBX TX"); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&sbx_xcvr::get_locked, this, dboard_iface::UNIT_TX)); + BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ + this->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&sbx_xcvr::set_tx_gain, this, _1, name)) + .set(sbx_tx_gain_ranges[name].start()); + this->get_tx_subtree()->create("gains/"+name+"/range") + .set(sbx_tx_gain_ranges[name]); + } + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&sbx_xcvr::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(sbx_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&sbx_xcvr::set_tx_ant, this, _1)) + .set(sbx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(sbx_tx_antennas); + this->get_tx_subtree()->create("connection").set("QI"); + this->get_tx_subtree()->create("enabled").set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset").set(false); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); @@ -138,18 +198,6 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ UHD_LOGV(often) << boost::format( "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" ) % RXIO_MASK % TXIO_MASK << std::endl; - - //set some default values - set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ - set_tx_gain(sbx_tx_gain_ranges[name].start(), name); - } - BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ - set_rx_gain(sbx_rx_gain_ranges[name].start(), name); - } } sbx_xcvr::~sbx_xcvr(void){ @@ -165,8 +213,8 @@ void sbx_xcvr::update_atr(void){ int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; - int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; - int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; + int rx_ld_led = get_locked(dboard_iface::UNIT_RX).to_bool() ? 0 : RX_LED_LD; + int tx_ld_led = get_locked(dboard_iface::UNIT_TX).to_bool() ? 0 : TX_LED_LD; int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; @@ -226,222 +274,13 @@ void sbx_xcvr::set_tx_lo_freq(double freq){ _tx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_TX, freq); } - double sbx_xcvr::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { return db_actual->set_lo_freq(unit, target_freq); } -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); - val = sbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); - val = sbx_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - - -bool sbx_xcvr::get_locked(dboard_iface::unit_t unit) { - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +sensor_value_t sbx_xcvr::get_locked(dboard_iface::unit_t unit) { + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp index 5ff84811a..c90cce456 100644 --- a/host/lib/usrp/dboard/db_sbx_common.hpp +++ b/host/lib/usrp/dboard/db_sbx_common.hpp @@ -113,9 +113,9 @@ static const freq_range_t sbx_enable_rx_lo_filter = list_of (range_t(0.4e9, 1.5e9)) ; -static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); +static const std::vector sbx_tx_antennas = list_of("TX/RX"); -static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); +static const std::vector sbx_rx_antennas = list_of("TX/RX")("RX2"); static const uhd::dict sbx_tx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 31.5, double(0.5))) @@ -133,12 +133,6 @@ public: sbx_xcvr(ctor_args_t args); ~sbx_xcvr(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - protected: uhd::dict _tx_gains, _rx_gains; @@ -149,8 +143,8 @@ protected: void set_tx_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void update_atr(void); @@ -167,7 +161,7 @@ protected: * \param unit which unit rx or tx * \return true for locked */ - bool get_locked(dboard_iface::unit_t unit); + sensor_value_t get_locked(dboard_iface::unit_t unit); /*! * Flash the LEDs diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp index b5aad8aa5..6e20d5882 100644 --- a/host/lib/usrp/dboard/db_sbx_version3.cpp +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -139,8 +139,8 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp index ea0acb699..d22e83b51 100644 --- a/host/lib/usrp/dboard/db_sbx_version4.cpp +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -142,8 +142,8 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; -- cgit v1.2.3 From 3c07f1d606296c0a6813a3a577e918926e43c478 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 18:04:55 -0700 Subject: wbx: bring WBX into the tree --- host/lib/usrp/dboard/CMakeLists.txt | 10 +- host/lib/usrp/dboard/db_wbx_common.cpp | 190 +++++++------------------------ host/lib/usrp/dboard/db_wbx_common.hpp | 57 ++++------ host/lib/usrp/dboard/db_wbx_simple.cpp | 185 ++++-------------------------- host/lib/usrp/dboard/db_wbx_version2.cpp | 130 +++++---------------- host/lib/usrp/dboard/db_wbx_version3.cpp | 130 +++++---------------- host/lib/usrp/dboard/db_wbx_version4.cpp | 140 ++++++----------------- 7 files changed, 188 insertions(+), 654 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 50662a96e..b000c7f33 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -26,11 +26,11 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index 63f70e3d5..daf6dbc98 100644 --- a/host/lib/usrp/dboard/db_wbx_common.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -58,6 +58,44 @@ static int rx_pga0_gain_to_iobits(double &gain){ * WBX Common Implementation **********************************************************************/ wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ + + //enable the clocks that we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&wbx_base::get_locked, this, dboard_iface::UNIT_RX)); + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::set_rx_gain, this, _1, name)) + .set(wbx_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(wbx_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("connection").set("IQ"); + this->get_rx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::set_rx_enabled, this, _1)) + .set(true); //start enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&wbx_base::get_locked, this, dboard_iface::UNIT_TX)); + this->get_tx_subtree()->create("connection").set("IQ"); + this->get_tx_subtree()->create("use_lo_offset").set(false); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + // instantiate subclass foo switch(get_rx_id().to_uint16()) { case 0x053: db_actual = wbx_versionx_sptr(new wbx_version2(this)); @@ -72,6 +110,7 @@ wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ /* We didn't recognize the version of the board... */ UHD_THROW_INVALID_CODE_PATH(); } + } @@ -88,18 +127,10 @@ void wbx_base::set_rx_enabled(bool enb){ ); } -void wbx_base::set_tx_enabled(bool enb){ - db_actual->set_tx_enabled(enb); -} - /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::set_tx_gain(double gain, const std::string &name){ - db_actual->set_tx_gain(gain, name); -} - -void wbx_base::set_rx_gain(double gain, const std::string &name){ +double wbx_base::set_rx_gain(double gain, const std::string &name){ assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = rx_pga0_gain_to_iobits(gain); @@ -109,150 +140,17 @@ void wbx_base::set_rx_gain(double gain, const std::string &name){ this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, io_bits, RX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return _rx_gains[name]; //returned shadowed } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::get_freq_range(void) { - return db_actual->get_freq_range(); -} - double wbx_base::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { return db_actual->set_lo_freq(unit, target_freq); } -bool wbx_base::get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +sensor_value_t wbx_base::get_locked(dboard_iface::unit_t unit){ + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void wbx_base::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "wbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_rx_gain_ranges.keys(), key.name, "wbx rx gain name"); - val = wbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0);; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = _rx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void wbx_base::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - _rx_enabled = val.as(); - this->set_rx_enabled(_rx_enabled); - return; - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "WBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::tx_get(const wax::obj &key_, wax::obj &val){ - db_actual->tx_get(key_, val); -} - -void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - _tx_enabled = val.as(); - this->set_tx_enabled(_tx_enabled); - return; - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "WBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - - diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 57e2a0fe6..3e41e04b7 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ #include #include #include +#include namespace uhd{ namespace usrp{ @@ -95,23 +97,9 @@ public: virtual ~wbx_base(void); protected: - virtual void set_rx_gain(double gain, const std::string &name); - virtual void set_tx_gain(double gain, const std::string &name); + virtual double set_rx_gain(double gain, const std::string &name); virtual void set_rx_enabled(bool enb); - virtual void set_tx_enabled(bool enb); - - virtual void rx_get(const wax::obj &key, wax::obj &val); - virtual void rx_set(const wax::obj &key, const wax::obj &val); - - virtual void tx_get(const wax::obj &key, wax::obj &val); - virtual void tx_set(const wax::obj &key, const wax::obj &val); - - /*! - * Retrieve the frequency range of the board. - * \return the frequency range as a freq_range_t - */ - virtual freq_range_t get_freq_range(void); /*! * Set the LO frequency for the particular dboard unit. @@ -128,8 +116,7 @@ protected: * \param unit which unit rx or tx * \return true for locked */ - virtual bool get_locked(dboard_iface::unit_t unit); - + virtual sensor_value_t get_locked(dboard_iface::unit_t unit); /*! * Version-agnostic ABC that wraps version-specific implementations of the @@ -143,11 +130,20 @@ protected: wbx_versionx() {} ~wbx_versionx(void) {} - virtual void set_tx_gain(double gain, const std::string &name) = 0; + virtual double set_tx_gain(double gain, const std::string &name) = 0; virtual void set_tx_enabled(bool enb) = 0; - virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; - virtual freq_range_t get_freq_range(void) = 0; virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + + property_tree::sptr get_rx_subtree(void){ + return self_base->get_rx_subtree(); + } + + property_tree::sptr get_tx_subtree(void){ + return self_base->get_tx_subtree(); + } }; @@ -161,14 +157,9 @@ protected: wbx_version2(wbx_base *_self_wbx_base); ~wbx_version2(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! @@ -181,14 +172,9 @@ protected: wbx_version3(wbx_base *_self_wbx_base); ~wbx_version3(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! @@ -201,14 +187,9 @@ protected: wbx_version4(wbx_base *_self_wbx_base); ~wbx_version4(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 789146854..1ac2a1704 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -40,9 +40,6 @@ static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); -//this will get set by a version-specific function call -static freq_range_t wbx_freq_range(0.0, 0.0); - /*********************************************************************** * The WBX simple implementation **********************************************************************/ @@ -51,17 +48,7 @@ public: wbx_simple(ctor_args_t args); ~wbx_simple(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); - double _rx_lo_freq, _tx_lo_freq; - void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); std::string _rx_ant; @@ -86,12 +73,33 @@ UHD_STATIC_BLOCK(reg_wbx_simple_dboards){ dboard_manager::register_dboard(0x0063, 0x004f, &make_wbx_simple, "WBX v4 + Simple GDB"); } - /*********************************************************************** * Structors **********************************************************************/ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->access("name").set( + this->get_rx_subtree()->access("name").get() + " + Simple GDB"); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&wbx_simple::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(wbx_rx_antennas); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->access("name").set( + this->get_tx_subtree()->access("name").get() + " + Simple GDB"); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&wbx_simple::set_tx_ant, this, _1)) + .set(wbx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(wbx_tx_antennas); + //set the gpio directions and atr controls (antenna switches all under ATR) this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, ANTSW_IO, ANTSW_IO); this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, ANTSW_IO, ANTSW_IO); @@ -107,14 +115,6 @@ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, ANT_TXRX, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ANT_RX2, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_RX2, ANTSW_IO); - - //get the frequency range of our WBX db - wbx_freq_range = this->get_freq_range(); - - //set some default values - set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); - set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); } wbx_simple::~wbx_simple(void){ @@ -139,144 +139,3 @@ void wbx_simple::set_tx_ant(const std::string &ant){ assert_has(wbx_tx_antennas, ant, "wbx tx antenna name"); //only one antenna option, do nothing } - -/*********************************************************************** - * Tuning - **********************************************************************/ -void wbx_simple::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, wbx_freq_range.clip(freq)); -} - -void wbx_simple::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, wbx_freq_range.clip(freq)); -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void wbx_simple::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - switch(get_rx_id().to_uint16()) { - case 0x053: - val = std::string("WBX RX + Simple GDB"); - return; - case 0x057: - val = std::string("WBX v3 RX + Simple GDB"); - return; - case 0x063: - val = std::string("WBX v4 RX + Simple GDB"); - return; - default: - UHD_THROW_INVALID_CODE_PATH(); - } - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = wbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = wbx_rx_antennas; - return; - - default: - //call into the base class for other properties - wbx_base::rx_get(key_, val); - } -} - -void wbx_simple::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - default: - //call into the base class for other properties - wbx_base::rx_set(key_, val); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_simple::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - switch(get_rx_id().to_uint16()) { - case 0x053: - val = std::string("WBX TX + Simple GDB"); - return; - case 0x057: - val = std::string("WBX v3 TX + Simple GDB"); - return; - case 0x063: - val = std::string("WBX v4 TX + Simple GDB"); - return; - default: - UHD_THROW_INVALID_CODE_PATH(); - } - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = wbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = wbx_tx_antennas; - return; - - default: - //call into the base class for other properties - wbx_base::tx_get(key_, val); - } -} - -void wbx_simple::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - default: - //call into the base class for other properties - wbx_base::tx_set(key_, val); - } -} diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp index 0b57a6e2d..d8a2b7e93 100644 --- a/host/lib/usrp/dboard/db_wbx_version2.cpp +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -75,9 +75,33 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v2"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v2_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v2"); + BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_tx_gain, this, _1, name)) + .set(wbx_v2_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v2_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v2_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version2::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v2_iobits = ADF4350_CE; @@ -99,17 +123,6 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()) { - set_tx_gain(wbx_v2_tx_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()) { - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version2::~wbx_version2(void){ @@ -119,7 +132,6 @@ wbx_base::wbx_version2::~wbx_version2(void){ /*********************************************************************** * Enables **********************************************************************/ - void wbx_base::wbx_version2::set_tx_enabled(bool enb){ self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | ADF4350_CE); @@ -129,7 +141,7 @@ void wbx_base::wbx_version2::set_tx_enabled(bool enb){ /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ +double wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ assert_has(wbx_v2_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ double dac_volts = tx_pga0_gain_to_dac_volts(gain); @@ -139,16 +151,13 @@ void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ self_base->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; //shadowed } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version2::get_freq_range(void) { - return wbx_v2_freq_range; -} - double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -247,8 +256,8 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -315,80 +324,3 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version2::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v2_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v2_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v2_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp index 3c5cdf5ba..4473bf1ae 100644 --- a/host/lib/usrp/dboard/db_wbx_version3.cpp +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -81,9 +81,33 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v3"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v3_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v3"); + BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_tx_gain, this, _1, name)) + .set(wbx_v3_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v3_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v3_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version3::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v3_iobits = TX_ATTN_MASK; @@ -105,18 +129,6 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ - set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version3::~wbx_version3(void){ @@ -136,7 +148,7 @@ void wbx_base::wbx_version3::set_tx_enabled(bool enb){ /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ +double wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); @@ -146,16 +158,13 @@ void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; //shadow } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version3::get_freq_range(void) { - return wbx_v3_freq_range; -} - double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -254,8 +263,8 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -322,80 +331,3 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version3::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v3_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp index b5104c9f1..981e4f4d2 100644 --- a/host/lib/usrp/dboard/db_wbx_version4.cpp +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -37,7 +37,7 @@ using namespace boost::assign; /*********************************************************************** * WBX Version 3 Constants **********************************************************************/ -static const uhd::dict wbx_v4_gain_ranges = map_list_of +static const uhd::dict wbx_v4_tx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 31, 1.0)) ; @@ -49,10 +49,10 @@ static const freq_range_t wbx_v4_freq_range(50.0e6, 2.2e9); **********************************************************************/ static int tx_pga0_gain_to_iobits(double &gain){ //clip the input - gain = wbx_v4_gain_ranges["PGA0"].clip(gain); + gain = wbx_v4_tx_gain_ranges["PGA0"].clip(gain); //convert to attenuation - double attn = wbx_v4_gain_ranges["PGA0"].stop() - gain; + double attn = wbx_v4_tx_gain_ranges["PGA0"].stop() - gain; //calculate the attenuation int attn_code = boost::math::iround(attn); @@ -69,7 +69,7 @@ static int tx_pga0_gain_to_iobits(double &gain){ ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; //the actual gain setting - gain = wbx_v4_gain_ranges["PGA0"].stop() - double(attn_code); + gain = wbx_v4_tx_gain_ranges["PGA0"].stop() - double(attn_code); return iobits; } @@ -82,9 +82,33 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v4"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v4_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v4"); + BOOST_FOREACH(const std::string &name, wbx_v4_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_tx_gain, this, _1, name)) + .set(wbx_v4_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v4_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v4_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version4::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v4_iobits = TX_ATTN_MASK; @@ -106,18 +130,6 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - BOOST_FOREACH(const std::string &name, wbx_v4_gain_ranges.keys()){ - set_tx_gain(wbx_v4_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version4::~wbx_version4(void){ @@ -137,8 +149,8 @@ void wbx_base::wbx_version4::set_tx_enabled(bool enb) { /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { - assert_has(wbx_v4_gain_ranges.keys(), name, "wbx tx gain name"); +double wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { + assert_has(wbx_v4_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); self_base->_tx_gains[name] = gain; @@ -147,16 +159,13 @@ void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version4::get_freq_range(void) { - return wbx_v4_freq_range; -} - double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -257,8 +266,8 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -325,80 +334,3 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version4::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v4_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v4_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v4_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -- cgit v1.2.3 From 45d7e5105e393a7c62bb2df40521fccb834e0110 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 18:18:56 -0700 Subject: wbx: fixed typo because it should tx --- host/lib/usrp/dboard/db_wbx_version2.cpp | 2 +- host/lib/usrp/dboard/db_wbx_version3.cpp | 2 +- host/lib/usrp/dboard/db_wbx_version4.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp index d8a2b7e93..e25cb2e4c 100644 --- a/host/lib/usrp/dboard/db_wbx_version2.cpp +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -95,7 +95,7 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v2_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v2_freq_range); diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp index 4473bf1ae..70981ce94 100644 --- a/host/lib/usrp/dboard/db_wbx_version3.cpp +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -101,7 +101,7 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v3_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v3_freq_range); diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp index 981e4f4d2..faaf9e3fd 100644 --- a/host/lib/usrp/dboard/db_wbx_version4.cpp +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -102,7 +102,7 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v4_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v4_freq_range); -- cgit v1.2.3 From f1434d7c52728cbf80e954b4c9414a94eec4c9ce Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 15:10:19 -0800 Subject: usrp2: fix channel mapping calculation --- host/lib/usrp/usrp2/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d144c08bf..8018875ec 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -405,7 +405,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].rx_chan_occ; if (chan < num_chan_so_far){ - const size_t dsp = num_chan_so_far - chan - 1; + const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( @@ -473,7 +473,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].tx_chan_occ; if (chan < num_chan_so_far){ - const size_t dsp = num_chan_so_far - chan - 1; + const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far; my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1 )); -- cgit v1.2.3 From 9d4350d74ea926999780ded0016c5ad51874ebec Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 7 Nov 2011 15:28:16 -0800 Subject: Updated typos in XCVR2450 dboard property tree code --- host/lib/usrp/dboard/db_xcvr2450.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index bdc6aa9fe..cf1637335 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -269,12 +269,12 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ .set(get_tx_id().to_pp_string()); this->get_tx_subtree()->create("sensors/lo_locked") .publish(boost::bind(&xcvr2450::get_locked, this)); - BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ - this->get_rx_subtree()->create("gains/"+name+"/value") - .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) - .set(xcvr_rx_gain_ranges[name].start()); - this->get_rx_subtree()->create("gains/"+name+"/range") - .set(xcvr_rx_gain_ranges[name]); + BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){ + this->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_tx_gain, this, _1, name)) + .set(xcvr_tx_gain_ranges[name].start()); + this->get_tx_subtree()->create("gains/"+name+"/range") + .set(xcvr_tx_gain_ranges[name]); } this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) -- cgit v1.2.3 From 902818f50bbd486138a7d4cd2ce9ba3661f4a732 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 16:53:47 -0800 Subject: uhd: removed wax and props utils --- host/include/uhd/CMakeLists.txt | 1 - host/include/uhd/deprecated.hpp | 170 --------------------------------- host/include/uhd/utils/CMakeLists.txt | 1 - host/include/uhd/utils/props.hpp | 81 ---------------- host/include/uhd/wax.hpp | 2 - host/lib/deprecated.cpp | 152 ----------------------------- host/lib/usrp/dboard/db_wbx_common.hpp | 1 - host/lib/usrp/dboard/db_wbx_simple.cpp | 4 +- host/lib/usrp/gps_ctrl.cpp | 3 +- host/lib/utils/CMakeLists.txt | 1 - host/lib/utils/props.cpp | 40 -------- 11 files changed, 3 insertions(+), 453 deletions(-) delete mode 100644 host/include/uhd/utils/props.hpp delete mode 100644 host/include/uhd/wax.hpp delete mode 100644 host/lib/utils/props.cpp (limited to 'host/lib/usrp') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 2b0c6ec14..1df04d577 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -32,7 +32,6 @@ INSTALL(FILES property_tree.hpp stream.hpp version.hpp - wax.hpp DESTINATION ${INCLUDE_DIR}/uhd COMPONENT headers ) diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index d918836f1..95cce58e9 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -2,176 +2,6 @@ //-- deprecated interfaces below, to be removed when the API is changed //---------------------------------------------------------------------- -// -// Copyright 2010-2011 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 . -// - -#ifndef INCLUDED_WAX_HPP -#define INCLUDED_WAX_HPP - -#include -#include -#include -#include -#include - -/*! - * WAX - it's a metaphor! - * - * The WAX framework allows an object to have generic/anyobj properties. - * These properties can be addressed through generic/anyobj identifiers. - * - * The WAX object itself is an anytype container much like boost::any. - * To retrieve the value of the appropriate type, use my_obj.as(). - * - * Proprties may be referenced though the [] overloaded operator. - * The [] operator returns a special proxy that allows for assigment. - * Also, the [] operators may be chained as in the folowing examples: - * my_obj[prop1][prop2][prop3] = value; - * value = my_obj[prop1][prop2][prop3].as(); - * - * Property nesting occurs when a WAX object gets another object's link. - * This special link is obtained through a call to my_obj.get_link(). - * - * Note: Do not put a class derived from wax::obj into an stl container. - * MSVC will compile the code, but the binaries will crash at runtime. - * Rather, use pointers or smart pointers to instances of the derived class. - */ - -namespace wax{ - - /*! - * WAX object base class: - * - * A wax obj has two major purposes: - * 1) to act as a polymorphic container, just like boost any - * 2) to provide a nested set/get properties interface - * - * Internally, the polymorphic container is handled by a boost any. - * For properties, a subclass should override the set and get methods. - * For property nesting, wax obj subclasses return special links - * to other wax obj subclasses, and the api handles the magic. - */ - class UHD_API obj{ - public: - - /*! - * Default constructor: - * The contents will be empty. - */ - obj(void); - - /*! - * Copy constructor: - * The contents will be cloned. - * \param o another wax::obj - */ - obj(const obj &o); - - /*! - * Templated any type constructor: - * The contents can be anything. - * Uses the boost::any to handle the magic. - * \param o an object of any type - */ - template obj(const T &o){ - _contents = o; - } - - /*! - * Destructor. - */ - virtual ~obj(void); - - /*! - * The chaining operator: - * This operator allows access objs with properties. - * A call to the [] operator will return a new proxy obj. - * The proxy object is an obj with special proxy contents. - * Assignment and casting can be used on this special object - * to access the property referenced by the obj key. - * \param key a key to identify a property within this obj - * \return a special wax obj that proxies the obj and key - */ - obj operator[](const obj &key); - - /*! - * The assignment operator: - * This operator allows for assignment of new contents. - * In the special case where this obj contains a proxy, - * the value will be set to the proxy's property reference. - * \param val the new value to assign to the wax obj - * \return a reference to this obj (*this) - */ - obj & operator=(const obj &val); - - /*! - * Get a link in the chain: - * When a wax obj returns another wax obj as part of a get call, - * the return value should be set to the result of this method. - * Doing so will ensure chain-ability of the returned object. - * \return an obj containing a valid link to a wax obj - */ - obj get_link(void) const; - - /*! - * Get the type of the contents of this obj. - * \return a reference to the type_info - */ - const std::type_info & type(void) const; - - /*! - * Cast this obj into the desired type. - * Usage: myobj.as() - * - * \return an object of the desired type - * \throw wax::bad_cast when the cast fails - */ - template T as(void) const{ - try{ - return boost::any_cast(resolve()); - } - catch(const boost::bad_any_cast &e){ - throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); - } - } - - private: - //private interface (override in subclasses) - virtual void get(const obj &, obj &); - virtual void set(const obj &, const obj &); - - /*! - * Resolve the contents of this obj. - * In the case where this obj is a proxy, - * the referenced property will be resolved. - * Otherwise, just get the private contents. - * \return a boost any type with contents - */ - boost::any resolve(void) const; - - //private contents of this obj - boost::any _contents; - - }; - -} //namespace wax - -#endif /* INCLUDED_WAX_HPP */ - // // Copyright 2010 Ettus Research LLC // diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index 0bf98fb67..48b8db885 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -26,7 +26,6 @@ INSTALL(FILES log.hpp msg.hpp pimpl.hpp - props.hpp safe_call.hpp safe_main.hpp static.hpp diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp deleted file mode 100644 index 81737423a..000000000 --- a/host/include/uhd/utils/props.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright 2010-2011 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 . -// - -#ifndef INCLUDED_UHD_UTILS_PROPS_HPP -#define INCLUDED_UHD_UTILS_PROPS_HPP - -#include -#include -#include -#include -#include - -namespace uhd{ - - //! The type for a vector of property names - typedef std::vector prop_names_t; - - /*! - * A named prop struct holds a key and a name. - * Allows properties to be sub-sectioned by name. - */ - struct UHD_API named_prop_t{ - const wax::obj key; - const std::string name; - - //! Convert the key to the specified type - template inline T as(void){ - return key.as(); - } - - /*! - * Utility function to convert generic key into a named prop. - * If the key was already a named prop, the prop will be split. - * Otherwise, the key will be the key, and the name will be used. - * \param key a reference to the prop object - * \param name a reference to the name object - * \return a named property struct with key and name - */ - static named_prop_t extract( - const wax::obj &key, const std::string &name = "" - ); - - /*! - * Create a new named prop from key and name. - * \param key the property key - * \param name the string name - */ - named_prop_t(const wax::obj &key, const std::string &name); - }; - - /*! - * Throw when getting a not-implemented or write-only property. - * Throw-site information will be included with this error. - */ - #define UHD_THROW_PROP_GET_ERROR() \ - throw uhd::key_error(UHD_THROW_SITE_INFO("cannot get this property")) - - /*! - * Throw when setting a not-implemented or read-only property. - * Throw-site information will be included with this error. - */ - #define UHD_THROW_PROP_SET_ERROR() \ - throw uhd::key_error(UHD_THROW_SITE_INFO("cannot set this property")) - -} //namespace uhd - -#endif /* INCLUDED_UHD_UTILS_PROPS_HPP */ diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp deleted file mode 100644 index a55e5465d..000000000 --- a/host/include/uhd/wax.hpp +++ /dev/null @@ -1,2 +0,0 @@ -//The wax API has been deprecated in favor of the properties interface -#include diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp index b659d1be5..0fc751eeb 100644 --- a/host/lib/deprecated.cpp +++ b/host/lib/deprecated.cpp @@ -2,158 +2,6 @@ //-- deprecated interfaces below, to be removed when the API is changed //---------------------------------------------------------------------- -// -// Copyright 2010-2011 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 -#include -#include -#include - -/*! - * The link args for internal use within this cpp file: - * - * It contains a link (in this case a pointer) to a wax object. - * Only the methods in this file may create or parse link args. - * The get_link method is the creator of a link args object. - * The [] operator will resolve the link and make the [] call. - * - * TODO: register the link args with the wax obj that it links to. - * That way, if the obj destructs, the link can be invalidated. - * The operator() will throw, rather than dereferencing bad memory. - */ -class link_args_t{ -public: - link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ - /* NOP */ - } - wax::obj & operator()(void) const{ - //recursively resolve link args to get at original pointer - if (_obj_ptr->type() == typeid(link_args_t)){ - return _obj_ptr->as()(); - } - return *const_cast(_obj_ptr); - } -private: - const wax::obj *_obj_ptr; -}; - -/*! - * The proxy args for internal use within this cpp file: - * - * It contains a link and a key for setting/getting a property. - * Only the methods in this file may create or parse proxy args. - * Class methods have special handling for the case when the - * wax obj contains an instance of the proxy args. - */ -class proxy_args_t{ -public: - proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ - _obj_link = obj_ptr->get_link(); - } - wax::obj & operator()(void) const{ - return _obj_link.as()(); - } - const wax::obj & key(void) const{ - return _key; - } -private: - wax::obj _obj_link; - const wax::obj _key; -}; - -/*********************************************************************** - * Structors - **********************************************************************/ -wax::obj::obj(void){ - /* NOP */ -} - -wax::obj::obj(const obj &o){ - _contents = o._contents; -} - -wax::obj::~obj(void){ - /* NOP */ -} - -/*********************************************************************** - * Special Operators - **********************************************************************/ -wax::obj wax::obj::operator[](const obj &key){ - if (_contents.type() == typeid(proxy_args_t)){ - obj val = resolve(); - //check if its a special link and call - if (val.type() == typeid(link_args_t)){ - return val.as()()[key]; - } - //unknown obj - throw uhd::type_error("cannot use [] on non wax::obj link"); - } - else{ - return proxy_args_t(this, key); - } -} - -wax::obj & wax::obj::operator=(const obj &val){ - if (_contents.type() == typeid(proxy_args_t)){ - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().set(proxy_args.key(), val); - } - else{ - _contents = val._contents; - } - return *this; -} - -/*********************************************************************** - * Public Methods - **********************************************************************/ -wax::obj wax::obj::get_link(void) const{ - return link_args_t(this); -} - -const std::type_info & wax::obj::type(void) const{ - return resolve().type(); -} - -/*********************************************************************** - * Private Methods - **********************************************************************/ -boost::any wax::obj::resolve(void) const{ - if (_contents.type() == typeid(proxy_args_t)){ - obj val; - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().get(proxy_args.key(), val); - return val.resolve(); - } - else{ - return _contents; - } -} - -void wax::obj::get(const obj &, obj &){ - throw uhd::type_error("Cannot call get on wax obj base class"); -} - -void wax::obj::set(const obj &, const obj &){ - throw uhd::type_error("Cannot call set on wax obj base class"); -} - #include #include #include diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 3e41e04b7..e7eb3f31a 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 1ac2a1704..f46ea70d1 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -36,9 +36,9 @@ using namespace boost::assign; /*********************************************************************** * The WBX Simple dboard constants **********************************************************************/ -static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); +static const std::vector wbx_tx_antennas = list_of("TX/RX"); -static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); +static const std::vector wbx_rx_antennas = list_of("TX/RX")("RX2"); /*********************************************************************** * The WBX simple implementation diff --git a/host/lib/usrp/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp index c645d2948..45fa1f39e 100644 --- a/host/lib/usrp/gps_ctrl.cpp +++ b/host/lib/usrp/gps_ctrl.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -121,7 +120,7 @@ public: return sensor_value_t("GPS lock status", locked(), "locked", "unlocked"); } else { - UHD_THROW_PROP_GET_ERROR(); + throw uhd::value_error("gps ctrl get_sensor unknown key: " + key); } } diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index fd3249099..19dde9a56 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -134,7 +134,6 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/props.cpp ${CMAKE_CURRENT_SOURCE_DIR}/static.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tasks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp diff --git a/host/lib/utils/props.cpp b/host/lib/utils/props.cpp deleted file mode 100644 index fc9f8e63f..000000000 --- a/host/lib/utils/props.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// 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 - -using namespace uhd; - -named_prop_t::named_prop_t( - const wax::obj &key, - const std::string &name -): - key(key), - name(name) -{ - /* NOP */ -} - -named_prop_t named_prop_t::extract( - const wax::obj &key, - const std::string &name -){ - if (key.type() == typeid(named_prop_t)){ - return key.as(); - } - return named_prop_t(key, name); -} -- cgit v1.2.3