diff options
Diffstat (limited to 'host/lib/usrp')
31 files changed, 502 insertions, 223 deletions
| diff --git a/host/lib/usrp/b100/b100_ctrl.cpp b/host/lib/usrp/b100/b100_ctrl.cpp index 7d40daa32..e6136c00e 100644 --- a/host/lib/usrp/b100/b100_ctrl.cpp +++ b/host/lib/usrp/b100/b100_ctrl.cpp @@ -165,7 +165,7 @@ int b100_ctrl_impl::write(boost::uint32_t addr, const ctrl_data_t &data) {      pkt.pkt_meta.seq = _seq++;      pkt.pkt_meta.len = pkt.data.size();      pkt.pkt_meta.addr = addr; -    boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)]; +    boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)] = {};      pack_ctrl_pkt(pkt_buff, pkt);      size_t result = send_pkt(pkt_buff); @@ -181,7 +181,7 @@ ctrl_data_t b100_ctrl_impl::read(boost::uint32_t addr, size_t len) {      pkt.pkt_meta.seq = _seq++;      pkt.pkt_meta.len = len;      pkt.pkt_meta.addr = addr; -    boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)]; +    boost::uint16_t pkt_buff[CTRL_PACKET_LENGTH / sizeof(boost::uint16_t)] = {};      //flush anything that might be in the queue      while (get_ctrl_data(pkt.data, 0.0)){ diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 61bc58bce..8b55494c5 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2012 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 @@ -150,6 +150,10 @@ UHD_STATIC_BLOCK(register_b100_device){   * Structors   **********************************************************************/  b100_impl::b100_impl(const device_addr_t &device_addr){ +    size_t initialization_count = 0; +    b100_impl_constructor_begin: +    initialization_count++; +      _tree = property_tree::make();      //extract the FPGA path for the B100 @@ -181,6 +185,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){      //load FPGA image, gpif is disabled while loading      this->enable_gpif(false);      _fx2_ctrl->usrp_load_fpga(b100_fpga_image); +    _fx2_ctrl->usrp_fpga_reset(false); //active low reset +    _fx2_ctrl->usrp_fpga_reset(true);      this->enable_gpif(true);      //create the control transport @@ -196,13 +202,28 @@ b100_impl::b100_impl(const device_addr_t &device_addr){          3, 4, //interface, endpoint          ctrl_xport_args      ); +    while (_ctrl_transport->get_recv_buff(0.0)){} //flush ctrl xport      ////////////////////////////////////////////////////////////////////      // Initialize FPGA wishbone communication      ////////////////////////////////////////////////////////////////////      _fpga_ctrl = b100_ctrl::make(_ctrl_transport); -    this->reset_gpif(6); //always reset first to ensure communication      _fpga_ctrl->poke32(B100_REG_GLOBAL_RESET, 0); //global fpga reset +    //perform a test peek operation +    try{ +        _fpga_ctrl->peek32(0); +    } +    //try reset once in the case of failure +    catch(const uhd::exception &e){ +        if (initialization_count > 1) throw; +        UHD_MSG(warning) << +            "The control endpoint was left in a bad state.\n" +            "Attempting endpoint re-enumeration...\n" << std::endl; +        _fpga_ctrl.reset(); +        _ctrl_transport.reset(); +        _fx2_ctrl->usrp_fx2_reset(); +        goto b100_impl_constructor_begin; +    }      this->check_fpga_compat(); //check after reset and making control      //////////////////////////////////////////////////////////////////// @@ -229,8 +250,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){              2, 6,          // IN interface, endpoint              1, 2,          // OUT interface, endpoint              data_xport_args    // param hints -        ) +        ), +        B100_MAX_PKT_BYTE_LIMIT      ); +    while (_data_transport->get_recv_buff(0.0)){} //flush data xport      ////////////////////////////////////////////////////////////////////      // Initialize the properties tree @@ -361,10 +384,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){      // create time control objects      ////////////////////////////////////////////////////////////////////      time64_core_200::readback_bases_type time64_rb_bases; -    time64_rb_bases.rb_secs_now = B100_REG_RB_TIME_NOW_SECS; -    time64_rb_bases.rb_ticks_now = B100_REG_RB_TIME_NOW_TICKS; -    time64_rb_bases.rb_secs_pps = B100_REG_RB_TIME_PPS_SECS; -    time64_rb_bases.rb_ticks_pps = B100_REG_RB_TIME_PPS_TICKS; +    time64_rb_bases.rb_hi_now = B100_REG_RB_TIME_NOW_HI; +    time64_rb_bases.rb_lo_now = B100_REG_RB_TIME_NOW_LO; +    time64_rb_bases.rb_hi_pps = B100_REG_RB_TIME_PPS_HI; +    time64_rb_bases.rb_lo_pps = B100_REG_RB_TIME_PPS_LO;      _time64 = time64_core_200::make(          _fpga_ctrl, B100_REG_SR_ADDR(B100_SR_TIME64), time64_rb_bases      ); @@ -388,6 +411,13 @@ b100_impl::b100_impl(const device_addr_t &device_addr){      _tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);      //////////////////////////////////////////////////////////////////// +    // create user-defined control objects +    //////////////////////////////////////////////////////////////////// +    _user = user_settings_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_USER_REGS)); +    _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs") +        .subscribe(boost::bind(&user_settings_core_200::set_reg, _user, _1)); + +    ////////////////////////////////////////////////////////////////////      // create dboard control objects      //////////////////////////////////////////////////////////////////// @@ -505,10 +535,6 @@ void b100_impl::update_clock_source(const std::string &source){  }  ////////////////// some GPIF preparation related stuff ///////////////// -void b100_impl::reset_gpif(const boost::uint16_t ep) { -    _fx2_ctrl->usrp_control_write(VRQ_RESET_GPIF, ep, ep, 0, 0); -} -  void b100_impl::enable_gpif(const bool en) {      _fx2_ctrl->usrp_control_write(VRQ_ENABLE_GPIF, en ? 1 : 0, 0, 0, 0);  } diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 96d90b14c..eab9c750b 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -29,6 +29,7 @@  #include "rx_dsp_core_200.hpp"  #include "tx_dsp_core_200.hpp"  #include "time64_core_200.hpp" +#include "user_settings_core_200.hpp"  #include <uhd/device.hpp>  #include <uhd/property_tree.hpp>  #include <uhd/utils/pimpl.hpp> @@ -43,14 +44,15 @@  #include <uhd/transport/usb_zero_copy.hpp>  #include <boost/weak_ptr.hpp> -static const double          B100_LINK_RATE_BPS = 256e6/8; //pratical link rate (< 480 Mbps) +static const double          B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps)  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 = 0x08; +static const boost::uint16_t B100_FW_COMPAT_NUM = 0x03; +static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x09;  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; +static const size_t          B100_MAX_PKT_BYTE_LIMIT = 2048;  //! Make a b100 dboard interface  uhd::usrp::dboard_iface::sptr make_b100_dboard_iface( @@ -84,6 +86,7 @@ private:      std::vector<rx_dsp_core_200::sptr> _rx_dsps;      tx_dsp_core_200::sptr _tx_dsp;      time64_core_200::sptr _time64; +    user_settings_core_200::sptr _user;      b100_clock_ctrl::sptr _clock_ctrl;      b100_codec_ctrl::sptr _codec_ctrl;      b100_ctrl::sptr _fpga_ctrl; @@ -120,7 +123,6 @@ private:      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 &); -    void reset_gpif(const boost::uint16_t);      void enable_gpif(const bool);      void clear_fpga_fifo(void);      void handle_async_message(uhd::transport::managed_recv_buffer::sptr); diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index 491e16eef..987a09f03 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -1,4 +1,19 @@ - +// +// Copyright 2010-2012 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 <http://www.gnu.org/licenses/>. +//  ////////////////////////////////////////////////////////////////  // @@ -27,10 +42,6 @@  #define B100_REG_MISC_SW         B100_REG_MISC_BASE + 2  #define B100_REG_MISC_CGEN_CTRL  B100_REG_MISC_BASE + 4  #define B100_REG_MISC_CGEN_ST    B100_REG_MISC_BASE + 6 -#define B100_REG_MISC_TEST       B100_REG_MISC_BASE + 8 -#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  /////////////////////////////////////////////////////  // Slave 1 -- UART @@ -65,10 +76,10 @@  #define B100_REG_RB_MUX_32_BASE  B100_REG_SLAVE(7) -#define B100_REG_RB_TIME_NOW_SECS   B100_REG_RB_MUX_32_BASE + 0 -#define B100_REG_RB_TIME_NOW_TICKS  B100_REG_RB_MUX_32_BASE + 4 -#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_TIME_NOW_HI     B100_REG_RB_MUX_32_BASE + 0 +#define B100_REG_RB_TIME_NOW_LO     B100_REG_RB_MUX_32_BASE + 4 +#define B100_REG_RB_TIME_PPS_HI     B100_REG_RB_MUX_32_BASE + 8 +#define B100_REG_RB_TIME_PPS_LO     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 @@ -92,9 +103,9 @@  #define B100_SR_TX_FRONT 54      // 5 regs (+0 to +4)  #define B100_SR_REG_TEST32 60    // 1 reg -#define B100_SR_CLEAR_RX_FIFO 61 // 1 reg -#define B100_SR_CLEAR_TX_FIFO 62 // 1 reg +#define B100_SR_CLEAR_FIFO 61    // 1 reg  #define B100_SR_GLOBAL_RESET 63  // 1 reg +#define B100_SR_USER_REGS 64     // 2 regs  #define B100_SR_GPIO 128 @@ -105,8 +116,7 @@  /////////////////////////////////////////////////  // Magic reset regs  //////////////////////////////////////////////// -#define B100_REG_CLEAR_RX           B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO) -#define B100_REG_CLEAR_TX           B100_REG_SR_ADDR(B100_SR_CLEAR_RX_FIFO) +#define B100_REG_CLEAR_FIFO         B100_REG_SR_ADDR(B100_SR_CLEAR_FIFO)  #define B100_REG_GLOBAL_RESET       B100_REG_SR_ADDR(B100_SR_GLOBAL_RESET)  #endif diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 494d5d123..674380cca 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -17,6 +17,7 @@  #include "recv_packet_demuxer.hpp"  #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp"  #include "../../transport/super_recv_packet_handler.hpp"  #include "../../transport/super_send_packet_handler.hpp"  #include "usrp_commands.h" @@ -41,12 +42,13 @@ using namespace uhd::transport;   **********************************************************************/  struct b100_impl::io_impl{      io_impl(void): -        async_msg_fifo(100/*messages deep*/) +        async_msg_fifo(1000/*messages deep*/)      { /* NOP */ }      zero_copy_if::sptr data_transport;      bounded_buffer<async_metadata_t> async_msg_fifo;      recv_packet_demuxer::sptr demuxer; +    double tick_rate;  };  /*********************************************************************** @@ -54,12 +56,8 @@ struct b100_impl::io_impl{   **********************************************************************/  void b100_impl::io_init(void){ -    //clear state machines -    _fpga_ctrl->poke32(B100_REG_CLEAR_RX, 0); -    _fpga_ctrl->poke32(B100_REG_CLEAR_TX, 0); - -    //set the expected packet size in USB frames -    _fpga_ctrl->poke32(B100_REG_MISC_RX_LEN, 4); +    //clear fifo state machines +    _fpga_ctrl->poke32(B100_REG_CLEAR_FIFO, 0);      //allocate streamer weak ptrs containers      _rx_streamers.resize(_rx_dsps.size()); @@ -85,26 +83,16 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){      }      if (if_packet_info.sid == B100_TX_ASYNC_SID and if_packet_info.packet_type != vrt::if_packet_info_t::PACKET_TYPE_DATA){ +          //fill in the async metadata          async_metadata_t metadata; -        metadata.channel = 0; -        metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; -        metadata.time_spec = time_spec_t( -            time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), _clock_ctrl->get_fpga_clock_rate() -        ); -        metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); +        load_metadata_from_buff(uhd::wtohx<boost::uint32_t>, metadata, if_packet_info, vrt_hdr, _io_impl->tick_rate); + +        //push the message onto the queue          _io_impl->async_msg_fifo.push_with_pop_on_full(metadata); -        if (metadata.event_code & -            ( async_metadata_t::EVENT_CODE_UNDERFLOW -            | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) -        ) UHD_MSG(fastpath) << "U"; -        else if (metadata.event_code & -            ( async_metadata_t::EVENT_CODE_SEQ_ERROR -            | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) -        ) UHD_MSG(fastpath) << "S"; -        else if (metadata.event_code & -            async_metadata_t::EVENT_CODE_TIME_ERROR -        ) UHD_MSG(fastpath) << "L"; + +        //print some fastpath messages +        standard_async_msg_prints(metadata);      }      else UHD_MSG(error) << "Unknown async packet" << std::endl;  } @@ -123,6 +111,8 @@ void b100_impl::update_rates(void){  }  void b100_impl::update_tick_rate(const double rate){ +    _io_impl->tick_rate = rate; +      //update the tick rate on all existing streamers -> thread safe      for (size_t i = 0; i < _rx_streamers.size(); i++){          boost::shared_ptr<sph::recv_packet_streamer> my_streamer = @@ -154,6 +144,8 @@ void b100_impl::update_tx_samp_rate(const size_t dspno, const double rate){      if (my_streamer.get() == NULL) return;      my_streamer->set_samp_rate(rate); +    const double adj = _tx_dsp->get_scaling_adjustment(); +    my_streamer->set_scale_factor(adj);  }  void b100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ @@ -202,15 +194,15 @@ 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<size_t>(1, 0) : args.channels; -    const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));      //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 +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ; -    const size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer size +    const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;      const size_t bpi = convert::get_bytes_per_item(args.otw_format);      const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); @@ -233,8 +225,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 -        if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear(); -        _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); +        _rx_dsps[dsp]->setup(args);          my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(              &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1          ), true /*flush*/); @@ -260,16 +251,15 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){      args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;      args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; -    if (args.otw_format != "sc16"){ -        throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); -    } -      //calculate packet size      static const size_t hdr_size = 0          + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) +        + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer +        - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ; -    static const size_t bpp = 2048 - hdr_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 @@ -291,8 +281,7 @@ tx_streamer::sptr b100_impl::get_tx_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];          UHD_ASSERT_THROW(dsp == 0); //always 0 -        if (not args.args.has_key("noclear")) _tx_dsp->clear(); -        if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]); +        _tx_dsp->setup(args);          my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(              &zero_copy_if::get_send_buff, _data_transport, _1          )); diff --git a/host/lib/usrp/common/async_packet_handler.hpp b/host/lib/usrp/common/async_packet_handler.hpp new file mode 100644 index 000000000..fef03483f --- /dev/null +++ b/host/lib/usrp/common/async_packet_handler.hpp @@ -0,0 +1,71 @@ +// +// Copyright 2012 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP +#define INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/vrt_if_packet.hpp> +#include <uhd/types/metadata.hpp> +#include <uhd/utils/byteswap.hpp> +#include <uhd/utils/msg.hpp> + +namespace uhd{ namespace usrp{ + +    template <typename to_host_type> +    void load_metadata_from_buff( +        const to_host_type &to_host, +        async_metadata_t &metadata, +        const transport::vrt::if_packet_info_t &if_packet_info, +        const boost::uint32_t *vrt_hdr, +        const double tick_rate, +        const size_t channel = 0 +    ){ +        const boost::uint32_t *payload = vrt_hdr + if_packet_info.num_header_words32; + +        //load into metadata +        metadata.channel = channel; +        metadata.has_time_spec = if_packet_info.has_tsf; +        metadata.time_spec = time_spec_t::from_ticks(if_packet_info.tsf, tick_rate); +        metadata.event_code = async_metadata_t::event_code_t(to_host(payload[0]) & 0xff); + +        //load user payload +        for (size_t i = 1; i < if_packet_info.num_payload_words32; i++){ +            if (i-1 == 4) break; //limit of 4 words32 +            metadata.user_payload[i-1] = to_host(payload[i]); +        } +    } + +    UHD_INLINE void standard_async_msg_prints(const async_metadata_t &metadata) +    { +        if (metadata.event_code & +            ( async_metadata_t::EVENT_CODE_UNDERFLOW +            | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) +        ) UHD_MSG(fastpath) << "U"; +        else if (metadata.event_code & +            ( async_metadata_t::EVENT_CODE_SEQ_ERROR +            | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) +        ) UHD_MSG(fastpath) << "S"; +        else if (metadata.event_code & +            async_metadata_t::EVENT_CODE_TIME_ERROR +        ) UHD_MSG(fastpath) << "L"; +    } + + +}} //namespace uhd::usrp + +#endif /* INCLUDED_LIBUHD_USRP_COMMON_ASYNC_PACKET_HANDLER_HPP */ diff --git a/host/lib/usrp/common/fx2_ctrl.cpp b/host/lib/usrp/common/fx2_ctrl.cpp index 3c6df7079..7b8920eb1 100644 --- a/host/lib/usrp/common/fx2_ctrl.cpp +++ b/host/lib/usrp/common/fx2_ctrl.cpp @@ -139,6 +139,15 @@ public:          _ctrl_transport = ctrl_transport;      } +    void usrp_fx2_reset(void){ +        unsigned char reset_y = 1; +        unsigned char reset_n = 0; +        usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_y, 1); +        usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); +        //wait for things to settle +        boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); +    } +      void usrp_load_firmware(std::string filestring, bool force)      {          const char *filename = filestring.c_str(); @@ -419,7 +428,7 @@ public:      {          UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes); -        unsigned char buff[max_i2c_data_bytes]; +        unsigned char buff[max_i2c_data_bytes] = {};          std::copy(bytes.begin(), bytes.end(), buff);          int ret = this->usrp_i2c_write(addr & 0xff, @@ -434,7 +443,7 @@ public:      {        UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes); -      unsigned char buff[max_i2c_data_bytes]; +      unsigned char buff[max_i2c_data_bytes] = {};        int ret = this->usrp_i2c_read(addr & 0xff,                                              buff,                                              num_bytes); diff --git a/host/lib/usrp/common/fx2_ctrl.hpp b/host/lib/usrp/common/fx2_ctrl.hpp index 691d64275..f2e060862 100644 --- a/host/lib/usrp/common/fx2_ctrl.hpp +++ b/host/lib/usrp/common/fx2_ctrl.hpp @@ -39,6 +39,9 @@ public:      //! Call init after the fpga is loaded      virtual void usrp_init(void) = 0; +    //! For emergency situations +    virtual void usrp_fx2_reset(void) = 0; +      /*!       * Load firmware in Intel HEX Format onto device        * \param filename name of firmware file @@ -116,6 +119,9 @@ public:      //! enable/disable the tx path      virtual void usrp_tx_enable(bool on) = 0; + +    //! reset the fpga +    virtual void usrp_fpga_reset(bool on) = 0;  };  }} //namespace uhd::usrp diff --git a/host/lib/usrp/cores/CMakeLists.txt b/host/lib/usrp/cores/CMakeLists.txt index 2aa8f6b99..aa5f0bcbb 100644 --- a/host/lib/usrp/cores/CMakeLists.txt +++ b/host/lib/usrp/cores/CMakeLists.txt @@ -1,5 +1,5 @@  # -# Copyright 2011 Ettus Research LLC +# Copyright 2011-2012 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 @@ -30,4 +30,5 @@ LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/tx_dsp_core_200.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/rx_frontend_core_200.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/tx_frontend_core_200.cpp +    ${CMAKE_CURRENT_SOURCE_DIR}/user_settings_core_200.cpp  ) diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 2e21cc895..0996952ff 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -18,6 +18,7 @@  #include "rx_dsp_core_200.hpp"  #include <uhd/types/dict.hpp>  #include <uhd/exception.hpp> +#include <uhd/utils/msg.hpp>  #include <uhd/utils/algorithm.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/thread/thread.hpp> //thread sleep @@ -27,7 +28,7 @@  #include <cmath>  #define REG_DSP_RX_FREQ       _dsp_base + 0 -//skip one right here +#define REG_DSP_RX_SCALE_IQ   _dsp_base + 4  #define REG_DSP_RX_DECIM      _dsp_base + 8  #define REG_DSP_RX_MUX        _dsp_base + 12 @@ -35,15 +36,15 @@  #define FLAG_DSP_RX_MUX_REAL_MODE (1 << 1)  #define REG_RX_CTRL_STREAM_CMD     _ctrl_base + 0 -#define REG_RX_CTRL_TIME_SECS      _ctrl_base + 4 -#define REG_RX_CTRL_TIME_TICKS     _ctrl_base + 8 +#define REG_RX_CTRL_TIME_HI        _ctrl_base + 4 +#define REG_RX_CTRL_TIME_LO        _ctrl_base + 8  #define REG_RX_CTRL_CLEAR          _ctrl_base + 12  #define REG_RX_CTRL_VRT_HDR        _ctrl_base + 16  #define REG_RX_CTRL_VRT_SID        _ctrl_base + 20  #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 +#define REG_RX_CTRL_FORMAT         REG_RX_CTRL_CLEAR //re-use clear address  template <class T> T ceil_log2(T num){      return std::ceil(std::log(num)/std::log(T(2))); @@ -60,6 +61,10 @@ public:      ):          _iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base), _sid(sid)      { +        //init to something so update method has reasonable defaults +        _scaling_adjustment = 1.0; +        _dsp_extra_scaling = 1.0; +          //This is a hack/fix for the lingering packet problem.          //The caller should also flush the recv transports          if (lingering_packet){ @@ -78,7 +83,6 @@ public:          _iface->poke32(REG_RX_CTRL_VRT_HDR, 0              | (0x1 << 28) //if data with stream id              | (0x1 << 26) //has trailer -            | (0x3 << 22) //integer time other              | (0x1 << 20) //fractional time sample count          );          _iface->poke32(REG_RX_CTRL_VRT_SID, _sid); @@ -117,8 +121,9 @@ public:          //issue the stream command          _iface->poke32(REG_RX_CTRL_STREAM_CMD, cmd_word); -        _iface->poke32(REG_RX_CTRL_TIME_SECS, boost::uint32_t(stream_cmd.time_spec.get_full_secs())); -        _iface->poke32(REG_RX_CTRL_TIME_TICKS, stream_cmd.time_spec.get_tick_count(_tick_rate)); //latches the command +        const boost::uint64_t ticks = (stream_cmd.stream_now)? 0 : stream_cmd.time_spec.to_ticks(_tick_rate); +        _iface->poke32(REG_RX_CTRL_TIME_HI, boost::uint32_t(ticks >> 32)); +        _iface->poke32(REG_RX_CTRL_TIME_LO, boost::uint32_t(ticks >> 0)); //latches the command      }      void set_mux(const std::string &mode, const bool fe_swapped){ @@ -175,12 +180,20 @@ public:          // Calculate closest multiplier constant to reverse gain absent scale multipliers          const double rate_pow = std::pow(double(decim & 0xff), 4);          _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow); +        this->update_scalar();          return _tick_rate/decim_rate;      } +    void update_scalar(void){ +        const double target_scalar = (1 << 16)*_scaling_adjustment/_dsp_extra_scaling; +        const boost::int32_t actual_scalar = boost::math::iround(target_scalar); +        _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small +        _iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar); +    } +      double get_scaling_adjustment(void){ -        return _scaling_adjustment/_fxpt_scale_adj; +        return _fxpt_scalar_correction*_host_extra_scaling/32767.;      }      double set_freq(const double freq_){ @@ -210,22 +223,27 @@ public:          if (_continuous_streaming) issue_stream_command(stream_cmd_t::STREAM_MODE_START_CONTINUOUS);      } -    void set_format(const std::string &format, const unsigned scale){ +    void setup(const uhd::stream_args_t &stream_args){ +        if (not stream_args.args.has_key("noclear")) this->clear(); +          unsigned format_word = 0; -        if (format == "sc16"){ +        if (stream_args.otw_format == "sc16"){              format_word = 0; -            _fxpt_scale_adj = 32767.; +            _dsp_extra_scaling = 1.0; +            _host_extra_scaling = 1.0;          } -        else if (format == "sc8"){ -            format_word = (1 << 18); -            _fxpt_scale_adj = 127. * scale; -            _fxpt_scale_adj /= 256; //engine 16to8 drops lower 8 bits -            _fxpt_scale_adj /= 4; //scale operation 2-bit pad +        else if (stream_args.otw_format == "sc8"){ +            format_word = (1 << 0); +            double peak = stream_args.args.cast<double>("peak", 1.0); +            peak = std::max(peak, 1.0/256); +            _host_extra_scaling = peak*256; +            _dsp_extra_scaling = peak*256;          } -        else throw uhd::value_error("USRP RX cannot handle requested wire format: " + format); +        else throw uhd::value_error("USRP RX cannot handle requested wire format: " + stream_args.otw_format); + +        this->update_scalar(); -        const unsigned scale_word = scale & 0x3ffff; //18 bits; -        _iface->poke32(REG_RX_CTRL_FORMAT, format_word | scale_word); +        _iface->poke32(REG_RX_CTRL_FORMAT, format_word);      }  private: @@ -233,7 +251,7 @@ private:      const size_t _dsp_base, _ctrl_base;      double _tick_rate, _link_rate;      bool _continuous_streaming; -    double _scaling_adjustment, _fxpt_scale_adj; +    double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;      const boost::uint32_t _sid;  }; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index 58be51eee..b01f751e9 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -19,6 +19,7 @@  #define INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP  #include <uhd/config.hpp> +#include <uhd/stream.hpp>  #include <uhd/types/ranges.hpp>  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> @@ -60,7 +61,7 @@ public:      virtual void handle_overflow(void) = 0; -    virtual void set_format(const std::string &format, const unsigned scale) = 0; +    virtual void setup(const uhd::stream_args_t &stream_args) = 0;  };  #endif /* INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/cores/time64_core_200.cpp b/host/lib/usrp/cores/time64_core_200.cpp index 23d1bdea2..e460d1106 100644 --- a/host/lib/usrp/cores/time64_core_200.cpp +++ b/host/lib/usrp/cores/time64_core_200.cpp @@ -20,11 +20,10 @@  #include <uhd/utils/assert_has.hpp>  #include <boost/math/special_functions/round.hpp> -#define REG_TIME64_SECS        _base + 0 -#define REG_TIME64_TICKS       _base + 4 +#define REG_TIME64_TICKS_HI    _base + 0 +#define REG_TIME64_TICKS_LO    _base + 4  #define REG_TIME64_FLAGS       _base + 8  #define REG_TIME64_IMM         _base + 12 -#define REG_TIME64_TPS         _base + 16  #define REG_TIME64_MIMO_SYNC   _base + 20 //lower byte is delay cycles  //pps flags (see above) @@ -59,39 +58,42 @@ public:      void set_tick_rate(const double rate){          _tick_rate = rate; -        _iface->poke32(REG_TIME64_TPS, boost::math::iround(rate));      }      uhd::time_spec_t get_time_now(void){          for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously -            const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_now); -            const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_now); -            if (secs != _iface->peek32(_readback_bases.rb_secs_now)) continue; -            return time_spec_t(secs, ticks, _tick_rate); +            const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_now); +            const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_now); +            if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_now)) continue; +            const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo; +            return time_spec_t::from_ticks(ticks, _tick_rate);          }          throw uhd::runtime_error("time64_core_200: get time now timeout");      }      uhd::time_spec_t get_time_last_pps(void){          for (size_t i = 0; i < 3; i++){ //special algorithm because we cant read 64 bits synchronously -            const boost::uint32_t secs = _iface->peek32(_readback_bases.rb_secs_pps); -            const boost::uint32_t ticks = _iface->peek32(_readback_bases.rb_ticks_pps); -            if (secs != _iface->peek32(_readback_bases.rb_secs_pps)) continue; -            return time_spec_t(secs, ticks, _tick_rate); +            const boost::uint32_t ticks_hi = _iface->peek32(_readback_bases.rb_hi_pps); +            const boost::uint32_t ticks_lo = _iface->peek32(_readback_bases.rb_lo_pps); +            if (ticks_hi != _iface->peek32(_readback_bases.rb_hi_pps)) continue; +            const boost::uint64_t ticks = (boost::uint64_t(ticks_hi) << 32) | ticks_lo; +            return time_spec_t::from_ticks(ticks, _tick_rate);          }          throw uhd::runtime_error("time64_core_200: get time last pps timeout");      }      void set_time_now(const uhd::time_spec_t &time){ -        _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate)); +        const boost::uint64_t ticks = time.to_ticks(_tick_rate); +        _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0));          _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NOW); -        _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3 +        _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3      }      void set_time_next_pps(const uhd::time_spec_t &time){ -        _iface->poke32(REG_TIME64_TICKS, time.get_tick_count(_tick_rate)); +        const boost::uint64_t ticks = time.to_ticks(_tick_rate); +        _iface->poke32(REG_TIME64_TICKS_LO, boost::uint32_t(ticks >> 0));          _iface->poke32(REG_TIME64_IMM, FLAG_TIME64_LATCH_NEXT_PPS); -        _iface->poke32(REG_TIME64_SECS, boost::uint32_t(time.get_full_secs())); //latches all 3 +        _iface->poke32(REG_TIME64_TICKS_HI, boost::uint32_t(ticks >> 32)); //latches all 3      }      void set_time_source(const std::string &source){ diff --git a/host/lib/usrp/cores/time64_core_200.hpp b/host/lib/usrp/cores/time64_core_200.hpp index ebd51a02f..7571573a5 100644 --- a/host/lib/usrp/cores/time64_core_200.hpp +++ b/host/lib/usrp/cores/time64_core_200.hpp @@ -31,8 +31,8 @@ public:      typedef boost::shared_ptr<time64_core_200> sptr;      struct readback_bases_type{ -        size_t rb_secs_now, rb_ticks_now; -        size_t rb_secs_pps, rb_ticks_pps; +        size_t rb_hi_now, rb_lo_now; +        size_t rb_hi_pps, rb_lo_pps;      };      //! makes a new time64 core from iface and slave base diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index c5de4e361..7f02d59ca 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -1,5 +1,5 @@  // -// Copyright 2011 Ettus Research LLC +// Copyright 2011-2012 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 @@ -18,10 +18,12 @@  #include "tx_dsp_core_200.hpp"  #include <uhd/types/dict.hpp>  #include <uhd/exception.hpp> +#include <uhd/utils/msg.hpp>  #include <uhd/utils/algorithm.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/math/special_functions/round.hpp>  #include <boost/math/special_functions/sign.hpp> +#include <boost/thread/thread.hpp> //sleep  #include <algorithm>  #include <cmath> @@ -29,8 +31,8 @@  #define REG_DSP_TX_SCALE_IQ      _dsp_base + 4  #define REG_DSP_TX_INTERP        _dsp_base + 8 -#define REG_TX_CTRL_NUM_CHAN        _ctrl_base + 0 -#define REG_TX_CTRL_CLEAR_STATE     _ctrl_base + 4 +#define REG_TX_CTRL_CLEAR           _ctrl_base + 0 +#define REG_TX_CTRL_FORMAT          _ctrl_base + 4  #define REG_TX_CTRL_REPORT_SID      _ctrl_base + 8  #define REG_TX_CTRL_POLICY          _ctrl_base + 12  #define REG_TX_CTRL_CYCLES_PER_UP   _ctrl_base + 16 @@ -58,14 +60,19 @@ public:      ):          _iface(iface), _dsp_base(dsp_base), _ctrl_base(ctrl_base), _sid(sid)      { +        //init to something so update method has reasonable defaults +        _scaling_adjustment = 1.0; +        _dsp_extra_scaling = 1.0; +          //init the tx control registers          this->clear();          this->set_underflow_policy("next_packet");      }      void clear(void){ -        _iface->poke32(REG_TX_CTRL_CLEAR_STATE, 1); //reset -        _iface->poke32(REG_TX_CTRL_NUM_CHAN, 0);    //1 channel +        _iface->poke32(REG_TX_CTRL_CLEAR, 1); //reset and flush technique +        boost::this_thread::sleep(boost::posix_time::milliseconds(10)); +        _iface->poke32(REG_TX_CTRL_CLEAR, 0);          _iface->poke32(REG_TX_CTRL_REPORT_SID, _sid);      } @@ -121,13 +128,24 @@ public:          // Calculate CIC interpolation (i.e., without halfband interpolators)          // Calculate closest multiplier constant to reverse gain absent scale multipliers -        double rate_cubed = std::pow(double(interp & 0xff), 3); -        const boost::int16_t scale = boost::math::iround((4096*std::pow(2, ceil_log2(rate_cubed)))/(1.65*rate_cubed)); -        _iface->poke32(REG_DSP_TX_SCALE_IQ, (boost::uint32_t(scale) << 16) | (boost::uint32_t(scale) << 0)); +        const double rate_pow = std::pow(double(interp & 0xff), 3); +        _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow); +        this->update_scalar();          return _tick_rate/interp_rate;      } +    void update_scalar(void){ +        const double target_scalar = (1 << 17)*_scaling_adjustment/_dsp_extra_scaling; +        const boost::int32_t actual_scalar = boost::math::iround(target_scalar); +        _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small +        _iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar); +    } + +    double get_scaling_adjustment(void){ +        return _fxpt_scalar_correction*_host_extra_scaling*32767.; +    } +      double set_freq(const double freq_){          //correct for outside of rate (wrap around)          double freq = std::fmod(freq_, _tick_rate); @@ -156,10 +174,38 @@ public:          _iface->poke32(REG_TX_CTRL_PACKETS_PER_UP, (packets_per_up == 0)? 0 : (FLAG_TX_CTRL_UP_ENB | packets_per_up));      } +    void setup(const uhd::stream_args_t &stream_args){ +        if (not stream_args.args.has_key("noclear")) this->clear(); + +        unsigned format_word = 0; +        if (stream_args.otw_format == "sc16"){ +            format_word = 0; +            _dsp_extra_scaling = 1.0; +            _host_extra_scaling = 1.0; +        } +        else if (stream_args.otw_format == "sc8"){ +            format_word = (1 << 0); +            double peak = stream_args.args.cast<double>("peak", 1.0); +            peak = std::max(peak, 1.0/256); +            _host_extra_scaling = 1.0/peak/256; +            _dsp_extra_scaling = 1.0/peak; +        } +        else throw uhd::value_error("USRP TX cannot handle requested wire format: " + stream_args.otw_format); + +        this->update_scalar(); + +        _iface->poke32(REG_TX_CTRL_FORMAT, format_word); + +        if (stream_args.args.has_key("underflow_policy")){ +            this->set_underflow_policy(stream_args.args["underflow_policy"]); +        } +    } +  private:      wb_iface::sptr _iface;      const size_t _dsp_base, _ctrl_base;      double _tick_rate, _link_rate; +    double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;      const boost::uint32_t _sid;  }; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp index 4b39a5b07..0e1cfb6bc 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp @@ -19,6 +19,7 @@  #define INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP  #include <uhd/config.hpp> +#include <uhd/stream.hpp>  #include <uhd/types/ranges.hpp>  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> @@ -44,14 +45,15 @@ public:      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;      virtual double set_freq(const double freq) = 0;      virtual void set_updates(const size_t cycles_per_up, const size_t packets_per_up) = 0; -    virtual void set_underflow_policy(const std::string &policy) = 0; - +    virtual void setup(const uhd::stream_args_t &stream_args) = 0;  };  #endif /* INCLUDED_LIBUHD_USRP_TX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/cores/user_settings_core_200.cpp b/host/lib/usrp/cores/user_settings_core_200.cpp new file mode 100644 index 000000000..d262631b1 --- /dev/null +++ b/host/lib/usrp/cores/user_settings_core_200.cpp @@ -0,0 +1,43 @@ +// +// Copyright 2012 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 <http://www.gnu.org/licenses/>. +// + +#include "user_settings_core_200.hpp" + +#define REG_USER_ADDR             _base + 0 +#define REG_USER_DATA             _base + 4 + +class user_settings_core_200_impl : public user_settings_core_200{ +public: +    user_settings_core_200_impl(wb_iface::sptr iface, const size_t base): +        _iface(iface), _base(base) +    { +        //NOP +    } + +    void set_reg(const user_reg_t ®){ +        _iface->poke32(REG_USER_ADDR, reg.first); +        _iface->poke32(REG_USER_DATA, reg.second); +    } + +private: +    wb_iface::sptr _iface; +    const size_t _base; +}; + +user_settings_core_200::sptr user_settings_core_200::make(wb_iface::sptr iface, const size_t base){ +    return sptr(new user_settings_core_200_impl(iface, base)); +} diff --git a/host/lib/usrp/cores/user_settings_core_200.hpp b/host/lib/usrp/cores/user_settings_core_200.hpp new file mode 100644 index 000000000..1f5d13de7 --- /dev/null +++ b/host/lib/usrp/cores/user_settings_core_200.hpp @@ -0,0 +1,36 @@ +// +// Copyright 2012 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP +#define INCLUDED_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include "wb_iface.hpp" + +class user_settings_core_200 : boost::noncopyable{ +public: +    typedef boost::shared_ptr<user_settings_core_200> sptr; +    typedef std::pair<boost::uint8_t, boost::uint32_t> user_reg_t; + +    static sptr make(wb_iface::sptr iface, const size_t base); + +    virtual void set_reg(const user_reg_t ®) = 0; +}; + +#endif /* INCLUDED_LIBUHD_USRP_USER_SETTINGS_CORE_200_HPP */ diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index f58138ae6..a01ce4a7b 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -326,10 +326,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){      // create time control objects      ////////////////////////////////////////////////////////////////////      time64_core_200::readback_bases_type time64_rb_bases; -    time64_rb_bases.rb_secs_now = E100_REG_RB_TIME_NOW_SECS; -    time64_rb_bases.rb_ticks_now = E100_REG_RB_TIME_NOW_TICKS; -    time64_rb_bases.rb_secs_pps = E100_REG_RB_TIME_PPS_SECS; -    time64_rb_bases.rb_ticks_pps = E100_REG_RB_TIME_PPS_TICKS; +    time64_rb_bases.rb_hi_now = E100_REG_RB_TIME_NOW_HI; +    time64_rb_bases.rb_lo_now = E100_REG_RB_TIME_NOW_LO; +    time64_rb_bases.rb_hi_pps = E100_REG_RB_TIME_PPS_HI; +    time64_rb_bases.rb_lo_pps = E100_REG_RB_TIME_PPS_LO;      _time64 = time64_core_200::make(          _fpga_ctrl, E100_REG_SR_ADDR(UE_SR_TIME64), time64_rb_bases      ); @@ -353,6 +353,13 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){      _tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources);      //////////////////////////////////////////////////////////////////// +    // create user-defined control objects +    //////////////////////////////////////////////////////////////////// +    _user = user_settings_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_USER_REGS)); +    _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs") +        .subscribe(boost::bind(&user_settings_core_200::set_reg, _user, _1)); + +    ////////////////////////////////////////////////////////////////////      // create dboard control objects      //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index 2ea890375..1d36cb2ac 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -25,6 +25,7 @@  #include "rx_dsp_core_200.hpp"  #include "tx_dsp_core_200.hpp"  #include "time64_core_200.hpp" +#include "user_settings_core_200.hpp"  #include <uhd/device.hpp>  #include <uhd/property_tree.hpp>  #include <uhd/utils/pimpl.hpp> @@ -48,7 +49,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 = 0x08; +static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x09;  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; @@ -92,6 +93,7 @@ private:      std::vector<rx_dsp_core_200::sptr> _rx_dsps;      tx_dsp_core_200::sptr _tx_dsp;      time64_core_200::sptr _time64; +    user_settings_core_200::sptr _user;      e100_clock_ctrl::sptr _clock_ctrl;      e100_codec_ctrl::sptr _codec_ctrl;      e100_ctrl::sptr _fpga_ctrl; diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index f24f5895b..75be2cfbe 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -1,4 +1,19 @@ - +// +// Copyright 2010-2012 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 <http://www.gnu.org/licenses/>. +//  ////////////////////////////////////////////////////////////////  // @@ -71,10 +86,10 @@  #define E100_REG_RB_MUX_32_BASE  E100_REG_SLAVE(7) -#define E100_REG_RB_TIME_NOW_SECS   E100_REG_RB_MUX_32_BASE + 0 -#define E100_REG_RB_TIME_NOW_TICKS  E100_REG_RB_MUX_32_BASE + 4 -#define E100_REG_RB_TIME_PPS_SECS   E100_REG_RB_MUX_32_BASE + 8 -#define E100_REG_RB_TIME_PPS_TICKS  E100_REG_RB_MUX_32_BASE + 12 +#define E100_REG_RB_TIME_NOW_HI     E100_REG_RB_MUX_32_BASE + 0 +#define E100_REG_RB_TIME_NOW_LO     E100_REG_RB_MUX_32_BASE + 4 +#define E100_REG_RB_TIME_PPS_HI     E100_REG_RB_MUX_32_BASE + 8 +#define E100_REG_RB_TIME_PPS_LO     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 @@ -101,9 +116,9 @@  #define UE_SR_TX_FRONT 54      // 5 regs (+0 to +4)  #define UE_SR_REG_TEST32 60    // 1 reg -#define UE_SR_CLEAR_RX_FIFO 61 // 1 reg -#define UE_SR_CLEAR_TX_FIFO 62 // 1 reg +#define UE_SR_CLEAR_FIFO 61    // 1 reg  #define UE_SR_GLOBAL_RESET 63  // 1 reg +#define UE_SR_USER_REGS 64     // 2 regs  #define UE_SR_GPIO 128 @@ -115,8 +130,7 @@  /////////////////////////////////////////////////  // Magic reset regs  //////////////////////////////////////////////// -#define E100_REG_CLEAR_RX           E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) -#define E100_REG_CLEAR_TX           E100_REG_SR_ADDR(UE_SR_CLEAR_RX_FIFO) +#define E100_REG_CLEAR_FIFO         E100_REG_SR_ADDR(UE_SR_CLEAR_FIFO)  #define E100_REG_GLOBAL_RESET       E100_REG_SR_ADDR(UE_SR_GLOBAL_RESET)  #endif diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 441e32a8d..e9608125f 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -17,6 +17,7 @@  #include "recv_packet_demuxer.hpp"  #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp"  #include "../../transport/super_recv_packet_handler.hpp"  #include "../../transport/super_send_packet_handler.hpp"  #include <linux/usrp_e.h> //ioctl structures and constants @@ -50,7 +51,7 @@ using namespace uhd::transport;   **********************************************************************/  struct e100_impl::io_impl{      io_impl(void): -        false_alarm(0), async_msg_fifo(100/*messages deep*/) +        false_alarm(0), async_msg_fifo(1000/*messages deep*/)      { /* NOP */ }      double tick_rate; //set by update tick rate method @@ -123,28 +124,13 @@ void e100_impl::io_impl::handle_irq(void){          //fill in the async metadata          async_metadata_t metadata; -        metadata.channel = 0; -        metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; -        metadata.time_spec = time_spec_t( -            time_t(if_packet_info.tsi), long(if_packet_info.tsf), tick_rate -        ); -        metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(data.buf, if_packet_info)); +        load_metadata_from_buff(uhd::wtohx<boost::uint32_t>, metadata, if_packet_info, data.buf, tick_rate);          //push the message onto the queue          async_msg_fifo.push_with_pop_on_full(metadata);          //print some fastpath messages -        if (metadata.event_code & -            ( async_metadata_t::EVENT_CODE_UNDERFLOW -            | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) -        ) UHD_MSG(fastpath) << "U"; -        else if (metadata.event_code & -            ( async_metadata_t::EVENT_CODE_SEQ_ERROR -            | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) -        ) UHD_MSG(fastpath) << "S"; -        else if (metadata.event_code & -            async_metadata_t::EVENT_CODE_TIME_ERROR -        ) UHD_MSG(fastpath) << "L"; +        standard_async_msg_prints(metadata);      }      //prepare for the next round @@ -164,9 +150,8 @@ void e100_impl::io_init(void){      _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE);      _io_impl->iface = _fpga_ctrl; -    //clear state machines -    _fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0); -    _fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0); +    //clear fifo state machines +    _fpga_ctrl->poke32(E100_REG_CLEAR_FIFO, 0);      //allocate streamer weak ptrs containers      _rx_streamers.resize(_rx_dsps.size()); @@ -217,6 +202,8 @@ void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){      if (my_streamer.get() == NULL) return;      my_streamer->set_samp_rate(rate); +    const double adj = _tx_dsp->get_scaling_adjustment(); +    my_streamer->set_scale_factor(adj);  }  void e100_impl::update_rates(void){ @@ -278,13 +265,13 @@ 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<size_t>(1, 0) : args.channels; -    const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));      //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 +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ;      const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size;      const size_t bpi = convert::get_bytes_per_item(args.otw_format); @@ -309,8 +296,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 -        if (not args.args.has_key("noclear")) _rx_dsps[dsp]->clear(); -        _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); +        _rx_dsps[dsp]->setup(args);          my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(              &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1          ), true /*flush*/); @@ -336,14 +322,13 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){      args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;      args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; -    if (args.otw_format != "sc16"){ -        throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); -    } -      //calculate packet size      static const size_t hdr_size = 0          + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) +        + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer +        - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used          - sizeof(vrt::if_packet_info_t().cid) //no class id ever used +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ;      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); @@ -367,8 +352,7 @@ tx_streamer::sptr e100_impl::get_tx_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];          UHD_ASSERT_THROW(dsp == 0); //always 0 -        if (not args.args.has_key("noclear")) _tx_dsp->clear(); -        if (args.args.has_key("underflow_policy")) _tx_dsp->set_underflow_policy(args.args["underflow_policy"]); +        _tx_dsp->setup(args);          my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(              &zero_copy_if::get_send_buff, _data_transport, _1          )); diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 6cd9f95bb..d9be19b83 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -445,6 +445,17 @@ public:          return _tree->list(mb_root(mboard) / "sensors");      } +    void set_user_register(const boost::uint8_t addr, const boost::uint32_t data, size_t mboard){ +        if (mboard != ALL_MBOARDS){ +            typedef std::pair<boost::uint8_t, boost::uint32_t> user_reg_t; +            _tree->access<user_reg_t>(mb_root(mboard) / "user/reg").set(user_reg_t(addr, data)); +            return; +        } +        for (size_t m = 0; m < get_num_mboards(); m++){ +            set_user_register(addr, data, m); +        } +    } +      /*******************************************************************       * RX methods       ******************************************************************/ diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index e9d9b65c2..f27135562 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -221,17 +221,17 @@ void usrp1_impl::io_init(void){      _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); -    //create a new vandal thread to poll xerflow conditions -    _io_impl->vandal_task = task::make(boost::bind( -        &usrp1_impl::vandal_conquest_loop, this -    )); -      //init as disabled, then call the real function (uses restore)      this->enable_rx(false);      this->enable_tx(false);      rx_stream_on_off(false);      tx_stream_on_off(false);      _io_impl->flush_send_buff(); + +    //create a new vandal thread to poll xerflow conditions +    _io_impl->vandal_task = task::make(boost::bind( +        &usrp1_impl::vandal_conquest_loop, this +    ));  }  void usrp1_impl::rx_stream_on_off(bool enb){ diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp index b8af8af06..90b3a92da 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp @@ -39,8 +39,8 @@ public:          _nsamps_remaining(0),          _stream_mode(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS),          _cmd_queue(2), -        _async_msg_queue(100), -        _inline_msg_queue(100), +        _async_msg_queue(1000), +        _inline_msg_queue(1000),          _stream_on_off(stream_on_off)      {          //synchronously spawn a new thread diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index ef8ae950d..430ea59c8 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -210,6 +210,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){      ////////////////////////////////////////////////////////////////////      // Initialize the properties tree      //////////////////////////////////////////////////////////////////// +    _rx_dc_offset_shadow = 0;      _tree = property_tree::make();      _tree->create<std::string>("/name").set("USRP1 Device");      const fs_path mb_path = "/mboards/0"; diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 1af1db860..0babf7445 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,9 +30,9 @@ extern "C" {  #endif  //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 8 +#define USRP2_FPGA_COMPAT_NUM 9  #define USRP2_FW_COMPAT_NUM 11 -#define USRP2_FW_VER_MINOR 1 +#define USRP2_FW_VER_MINOR 2  //used to differentiate control packets over data port  #define USRP2_INVALID_VRT_HEADER 0 diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index e3fa46920..d32ffb62c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -16,6 +16,7 @@  //  #include "validate_subdev_spec.hpp" +#include "async_packet_handler.hpp"  #include "../../transport/super_recv_packet_handler.hpp"  #include "../../transport/super_send_packet_handler.hpp"  #include "usrp2_impl.hpp" @@ -135,7 +136,8 @@ private:  struct usrp2_impl::io_impl{      io_impl(void): -        async_msg_fifo(100/*messages deep*/) +        async_msg_fifo(1000/*messages deep*/), +        tick_rate(1 /*non-zero default*/)      {          /* NOP */      } @@ -201,12 +203,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(                  //fill in the async metadata                  async_metadata_t metadata; -                metadata.channel = index; -                metadata.has_time_spec = if_packet_info.has_tsi and if_packet_info.has_tsf; -                metadata.time_spec = time_spec_t( -                    time_t(if_packet_info.tsi), size_t(if_packet_info.tsf), tick_rate -                ); -                metadata.event_code = async_metadata_t::event_code_t(sph::get_context_code(vrt_hdr, if_packet_info)); +                load_metadata_from_buff(uhd::ntohx<boost::uint32_t>, metadata, if_packet_info, vrt_hdr, tick_rate, index);                  //catch the flow control packets and react                  if (metadata.event_code == 0){ @@ -217,17 +214,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(                  //else UHD_MSG(often) << "metadata.event_code " << metadata.event_code << std::endl;                  async_msg_fifo.push_with_pop_on_full(metadata); -                if (metadata.event_code & -                    ( async_metadata_t::EVENT_CODE_UNDERFLOW -                    | async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET) -                ) UHD_MSG(fastpath) << "U"; -                else if (metadata.event_code & -                    ( async_metadata_t::EVENT_CODE_SEQ_ERROR -                    | async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST) -                ) UHD_MSG(fastpath) << "S"; -                else if (metadata.event_code & -                    async_metadata_t::EVENT_CODE_TIME_ERROR -                ) UHD_MSG(fastpath) << "L"; +                standard_async_msg_prints(metadata);              }              else{                  //TODO unknown received packet, may want to print error... @@ -307,6 +294,8 @@ void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, co      if (my_streamer.get() == NULL) return;      my_streamer->set_samp_rate(rate); +    const double adj = _mbc[mb].tx_dsp->get_scaling_adjustment(); +    my_streamer->set_scale_factor(adj);  }  void usrp2_impl::update_rates(void){ @@ -380,13 +369,13 @@ 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<size_t>(1, 0) : args.channels; -    const unsigned sc8_scalar = unsigned(args.args.cast<double>("scalar", 0x400));      //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 +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ;      const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size;      const size_t bpi = convert::get_bytes_per_item(args.otw_format); @@ -416,8 +405,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 = 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 -                if (not args.args.has_key("noclear")) _mbc[mb].rx_dsps[dsp]->clear(); -                _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); +                _mbc[mb].rx_dsps[dsp]->setup(args);                  my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(                      &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1                  ), true /*flush*/); @@ -447,15 +435,14 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){      args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format;      args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels; -    if (args.otw_format != "sc16"){ -        throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); -    } -      //calculate packet size      static const size_t hdr_size = 0 -        + vrt::max_if_hdr_words32*sizeof(boost::uint32_t)          + vrt_send_header_offset_words32*sizeof(boost::uint32_t) +        + 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 +        - sizeof(vrt::if_packet_info_t().sid) //no stream id ever used +        - sizeof(vrt::if_packet_info_t().tsi) //no int time ever used      ;      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); @@ -485,10 +472,9 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){              if (chan < num_chan_so_far){                  const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far;                  if (not args.args.has_key("noclear")){ -                    _mbc[mb].tx_dsp->clear();                      _io_impl->fc_mons[abs]->clear();                  } -                if (args.args.has_key("underflow_policy")) _mbc[mb].tx_dsp->set_underflow_policy(args.args["underflow_policy"]); +                _mbc[mb].tx_dsp->setup(args);                  my_streamer->set_xport_chan_get_buff(chan_i, boost::bind(                      &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1                  )); diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 4830c10d9..eeba6756e 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -87,7 +87,7 @@ public:          //Obtain the firmware's compat number.          //Save the response compat number for communication.          //TODO can choose to reject certain older compat numbers -        usrp2_ctrl_data_t ctrl_data; +        usrp2_ctrl_data_t ctrl_data = usrp2_ctrl_data_t();          ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);          ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);          if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE) @@ -126,10 +126,9 @@ public:      bool is_device_locked(void){          boost::uint32_t lock_secs = this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_LOCK_TIME);          boost::uint32_t lock_gpid = this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_PEEK32>(U2_FW_REG_LOCK_GPID); -        boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM);          //if the difference is larger, assume not locked anymore -        if (curr_secs - lock_secs >= 3) return false; +        if (this->get_curr_secs() - lock_secs >= 3) return false;          //otherwise only lock if the device hash is different that ours          return lock_gpid != boost::uint32_t(get_gpid()); @@ -137,12 +136,16 @@ public:      void lock_task(void){          //re-lock in task -        boost::uint32_t curr_secs = this->peek32(U2_REG_TIME64_SECS_RB_IMM); -        this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, curr_secs); +        this->get_reg<boost::uint32_t, USRP2_REG_ACTION_FW_POKE32>(U2_FW_REG_LOCK_TIME, this->get_curr_secs());          //sleep for a bit          boost::this_thread::sleep(boost::posix_time::milliseconds(1500));      } +    boost::uint32_t get_curr_secs(void){ +        //may not be the right tick rate, but this is ok for locking purposes +        return boost::uint32_t(this->peek32(U2_REG_TIME64_LO_RB_IMM)/100e6); +    } +  /***********************************************************************   * Peek and Poke   **********************************************************************/ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index ef7151cee..2077ab009 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -546,10 +546,10 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          // create time control objects          ////////////////////////////////////////////////////////////////          time64_core_200::readback_bases_type time64_rb_bases; -        time64_rb_bases.rb_secs_now = U2_REG_TIME64_SECS_RB_IMM; -        time64_rb_bases.rb_ticks_now = U2_REG_TIME64_TICKS_RB_IMM; -        time64_rb_bases.rb_secs_pps = U2_REG_TIME64_SECS_RB_PPS; -        time64_rb_bases.rb_ticks_pps = U2_REG_TIME64_TICKS_RB_PPS; +        time64_rb_bases.rb_hi_now = U2_REG_TIME64_HI_RB_IMM; +        time64_rb_bases.rb_lo_now = U2_REG_TIME64_LO_RB_IMM; +        time64_rb_bases.rb_hi_pps = U2_REG_TIME64_HI_RB_PPS; +        time64_rb_bases.rb_lo_pps = U2_REG_TIME64_LO_RB_PPS;          _mbc[mb].time64 = time64_core_200::make(              _mbc[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles          ); @@ -572,6 +572,13 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          static const std::vector<std::string> clock_sources = boost::assign::list_of("internal")("external")("mimo");          _tree->create<std::vector<std::string> >(mb_path / "clock_source/options").set(clock_sources); +        //////////////////////////////////////////////////////////////////// +        // create user-defined control objects +        //////////////////////////////////////////////////////////////////// +        _mbc[mb].user = user_settings_core_200::make(_mbc[mb].iface, U2_REG_SR_ADDR(SR_USER_REGS)); +        _tree->create<user_settings_core_200::user_reg_t>(mb_path / "user/regs") +            .subscribe(boost::bind(&user_settings_core_200::set_reg, _mbc[mb].user, _1)); +          ////////////////////////////////////////////////////////////////          // create dboard control objects          //////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 278dc713e..882a61f80 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -26,6 +26,7 @@  #include "rx_dsp_core_200.hpp"  #include "tx_dsp_core_200.hpp"  #include "time64_core_200.hpp" +#include "user_settings_core_200.hpp"  #include <uhd/property_tree.hpp>  #include <uhd/usrp/gps_ctrl.hpp>  #include <uhd/device.hpp> @@ -91,6 +92,7 @@ private:          std::vector<boost::weak_ptr<uhd::tx_streamer> > tx_streamers;          tx_dsp_core_200::sptr tx_dsp;          time64_core_200::sptr time64; +        user_settings_core_200::sptr user;          std::vector<uhd::transport::zero_copy_if::sptr> rx_dsp_xports;          uhd::transport::zero_copy_if::sptr tx_dsp_xport;          uhd::usrp::dboard_manager::sptr dboard_manager; diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 179a930c6..e14798ecb 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -1,5 +1,5 @@  // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2012 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 @@ -39,7 +39,7 @@  #define SR_SIMTIMER   8   // 2  #define SR_TIME64    10   // 6  #define SR_BUF_POOL  16   // 4 - +#define SR_USER_REGS 20   // 2  #define SR_RX_FRONT  24   // 5  #define SR_RX_CTRL0  32   // 9  #define SR_RX_DSP0   48   // 7 @@ -97,11 +97,11 @@  ////////////////////////////////////////////////  #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_TIME64_HI_RB_IMM READBACK_BASE + 4*10 +#define U2_REG_TIME64_LO_RB_IMM READBACK_BASE + 4*11  #define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12  #define U2_REG_IRQ_RB READBACK_BASE + 4*13 -#define U2_REG_TIME64_SECS_RB_PPS READBACK_BASE + 4*14 -#define U2_REG_TIME64_TICKS_RB_PPS READBACK_BASE + 4*15 +#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4*14 +#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4*15  #endif /* INCLUDED_USRP2_REGS_HPP */ | 
