diff options
Diffstat (limited to 'host/lib/usrp2/usrp2_impl.cpp')
| -rw-r--r-- | host/lib/usrp2/usrp2_impl.cpp | 276 | 
1 files changed, 176 insertions, 100 deletions
| diff --git a/host/lib/usrp2/usrp2_impl.cpp b/host/lib/usrp2/usrp2_impl.cpp index 1c85aae9c..7dc9ac812 100644 --- a/host/lib/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp2/usrp2_impl.cpp @@ -31,6 +31,7 @@  #include <boost/foreach.hpp>  #include <boost/lexical_cast.hpp>  #include <boost/bind.hpp> +#include <boost/assign/list_of.hpp>  #include <boost/asio/ip/address_v4.hpp>  #include <boost/asio.hpp> //used for htonl and ntohl @@ -293,54 +294,54 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){      ////////////////////////////////////////////////////////////////////      _tree = property_tree::make(); -    _mboard_stuff.resize(device_args.size()); -    for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){ - -        const std::string addr = device_args[mb]["addr"]; -        property_tree::path_type mb_path = str(boost::format("/mboards/%u") % mb); +    for (size_t mbi = 0; mbi < device_args.size(); mbi++){ +        const device_addr_t device_args_i = device_args[mbi]; +        const std::string mb = boost::lexical_cast<std::string>(mbi); +        const std::string addr = device_args_i["addr"]; +        property_tree::path_type mb_path = "/mboards/" + mb;          ////////////////////////////////////////////////////////////////          // construct transports for dsp and async errors          ////////////////////////////////////////////////////////////////          UHD_LOG << "Making transport for DSP0..." << std::endl; -        _mboard_stuff[mb].dsp_xports.push_back(udp_zero_copy::make( -            addr, BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_args[mb] +        _mbc[mb].dsp_xports.push_back(udp_zero_copy::make( +            addr, BOOST_STRINGIZE(USRP2_UDP_DSP0_PORT), device_args_i          )); -        init_xport(_mboard_stuff[mb].dsp_xports.back()); +        init_xport(_mbc[mb].dsp_xports.back());          UHD_LOG << "Making transport for DSP1..." << std::endl; -        _mboard_stuff[mb].dsp_xports.push_back(udp_zero_copy::make( -            addr, BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_args[mb] +        _mbc[mb].dsp_xports.push_back(udp_zero_copy::make( +            addr, BOOST_STRINGIZE(USRP2_UDP_DSP1_PORT), device_args_i          )); -        init_xport(_mboard_stuff[mb].dsp_xports.back()); +        init_xport(_mbc[mb].dsp_xports.back());          UHD_LOG << "Making transport for ERR0..." << std::endl; -        _mboard_stuff[mb].err_xports.push_back(udp_zero_copy::make( +        _mbc[mb].err_xports.push_back(udp_zero_copy::make(              addr, BOOST_STRINGIZE(USRP2_UDP_ERR0_PORT), device_addr_t()          )); -        init_xport(_mboard_stuff[mb].err_xports.back()); +        init_xport(_mbc[mb].err_xports.back());          ////////////////////////////////////////////////////////////////          // create the iface that controls i2c, spi, uart, and wb          //////////////////////////////////////////////////////////////// -        _mboard_stuff[mb].iface = usrp2_iface::make(udp_simple::make_connected( +        _mbc[mb].iface = usrp2_iface::make(udp_simple::make_connected(              addr, BOOST_STRINGIZE(USRP2_UDP_CTRL_PORT)          )); -        _tree->create<std::string>(mb_path / "name").set(_mboard_stuff[mb].iface->get_cname()); +        _tree->create<std::string>(mb_path / "name").set(_mbc[mb].iface->get_cname());          ////////////////////////////////////////////////////////////////          // setup the mboard eeprom          ////////////////////////////////////////////////////////////////          _tree->create<mboard_eeprom_t>(mb_path / "eeprom") -            .set(_mboard_stuff[mb].iface->mb_eeprom) +            .set(_mbc[mb].iface->mb_eeprom)              .subscribe(boost::bind(&usrp2_impl::set_mb_eeprom, this, mb, _1));          ////////////////////////////////////////////////////////////////          // create clock control objects          //////////////////////////////////////////////////////////////// -        _mboard_stuff[mb].clock = usrp2_clock_ctrl::make(_mboard_stuff[mb].iface); +        _mbc[mb].clock = usrp2_clock_ctrl::make(_mbc[mb].iface);          _tree->create<double>(mb_path / "tick_rate") -            .publish(boost::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mboard_stuff[mb].clock)) +            .publish(boost::bind(&usrp2_clock_ctrl::get_master_clock_rate, _mbc[mb].clock))              .subscribe(boost::bind(&usrp2_impl::update_tick_rate, this, _1));          //////////////////////////////////////////////////////////////// @@ -348,8 +349,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          ////////////////////////////////////////////////////////////////          property_tree::path_type rx_codec_path = mb_path / "rx_codecs/A";          property_tree::path_type tx_codec_path = mb_path / "tx_codecs/A"; -        _mboard_stuff[mb].codec = usrp2_codec_ctrl::make(_mboard_stuff[mb].iface); -        switch(_mboard_stuff[mb].iface->get_rev()){ +        _mbc[mb].codec = usrp2_codec_ctrl::make(_mbc[mb].iface); +        switch(_mbc[mb].iface->get_rev()){          case usrp2_iface::USRP_N200:          case usrp2_iface::USRP_N210:          case usrp2_iface::USRP_N200_R4: @@ -357,10 +358,10 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){              _tree->create<std::string>(rx_codec_path / "name").set("ads62p44");              _tree->create<meta_range_t>(rx_codec_path / "gains/digital/range").set(meta_range_t(0, 6.0, 0.5));              _tree->create<double>(rx_codec_path / "gains/digital/value") -                .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mboard_stuff[mb].codec, _1)); +                .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_gain, _mbc[mb].codec, _1));              _tree->create<meta_range_t>(rx_codec_path / "gains/fine/range").set(meta_range_t(0, 0.5, 0.05));              _tree->create<double>(rx_codec_path / "gains/fine/value") -                .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mboard_stuff[mb].codec, _1)); +                .subscribe(boost::bind(&usrp2_codec_ctrl::set_rx_digital_fine_gain, _mbc[mb].codec, _1));          }break;          case usrp2_iface::USRP2_REV3: @@ -377,14 +378,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          ////////////////////////////////////////////////////////////////          // create gpsdo control objects          //////////////////////////////////////////////////////////////// -        if (_mboard_stuff[mb].iface->mb_eeprom["gpsdo"] == "internal"){ -            _mboard_stuff[mb].gps = gps_ctrl::make( -                _mboard_stuff[mb].iface->get_gps_write_fn(), -                _mboard_stuff[mb].iface->get_gps_read_fn() +        if (_mbc[mb].iface->mb_eeprom["gpsdo"] == "internal"){ +            _mbc[mb].gps = gps_ctrl::make( +                _mbc[mb].iface->get_gps_write_fn(), +                _mbc[mb].iface->get_gps_read_fn()              ); -            BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].gps->get_sensors()){ +            BOOST_FOREACH(const std::string &name, _mbc[mb].gps->get_sensors()){                  _tree->create<sensor_value_t>(mb_path / "sensors" / name) -                    .publish(boost::bind(&gps_ctrl::get_sensor, _mboard_stuff[mb].gps, name)); +                    .publish(boost::bind(&gps_ctrl::get_sensor, _mbc[mb].gps, name));              }          } @@ -396,27 +397,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          _tree->create<sensor_value_t>(mb_path / "sensors/ref_locked")              .publish(boost::bind(&usrp2_impl::get_ref_locked, this, mb)); - - -        //TODO //initialize VITA time to GPS time - -        //TODO clock source, time source -        //and if gps is present, set to external automatically - - - - - - -          ////////////////////////////////////////////////////////////////          // create frontend control objects          //////////////////////////////////////////////////////////////// -        _mboard_stuff[mb].rx_fe = rx_frontend_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_FRONT) +        _mbc[mb].rx_fe = rx_frontend_core_200::make( +            _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_FRONT)          ); -        _mboard_stuff[mb].tx_fe = tx_frontend_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT) +        _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<subdev_spec_t>(mb_path / "rx_subdev_spec") @@ -427,48 +415,48 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          ////////////////////////////////////////////////////////////////          // create rx dsp control objects          //////////////////////////////////////////////////////////////// -        _mboard_stuff[mb].rx_dsps.push_back(rx_dsp_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP0), U2_REG_SR_ADDR(SR_RX_CTRL0), USRP2_RX_SID_BASE + 0, true +        _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make( +            _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP0), U2_REG_SR_ADDR(SR_RX_CTRL0), USRP2_RX_SID_BASE + 0, true          )); -        _mboard_stuff[mb].rx_dsps.push_back(rx_dsp_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP1), U2_REG_SR_ADDR(SR_RX_CTRL1), USRP2_RX_SID_BASE + 1, true +        _mbc[mb].rx_dsps.push_back(rx_dsp_core_200::make( +            _mbc[mb].iface, U2_REG_SR_ADDR(SR_RX_DSP1), U2_REG_SR_ADDR(SR_RX_CTRL1), USRP2_RX_SID_BASE + 1, true          )); -        for (size_t dspno = 0; dspno < _mboard_stuff[mb].rx_dsps.size(); dspno++){ +        for (size_t dspno = 0; dspno < _mbc[mb].rx_dsps.size(); dspno++){              _tree->access<double>(mb_path / "tick_rate") -                .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _mboard_stuff[mb].rx_dsps[dspno], _1)); +                .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _mbc[mb].rx_dsps[dspno], _1));              //This is a hack/fix for the lingering packet problem.              //The dsp core starts streaming briefly... now we flush -            _mboard_stuff[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering -            _mboard_stuff[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected +            _mbc[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering +            _mbc[mb].dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected              property_tree::path_type rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno);              _tree->create<double>(rx_dsp_path / "rate/value") -                .subscribe_master(boost::bind(&rx_dsp_core_200::set_host_rate, _mboard_stuff[mb].rx_dsps[dspno], _1)) +                .subscribe_master(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));              _tree->create<double>(rx_dsp_path / "freq/value") -                .subscribe_master(boost::bind(&rx_dsp_core_200::set_freq, _mboard_stuff[mb].rx_dsps[dspno], _1)); +                .subscribe_master(boost::bind(&rx_dsp_core_200::set_freq, _mbc[mb].rx_dsps[dspno], _1));              _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd") -                .subscribe(boost::bind(&rx_dsp_core_200::issue_stream_command, _mboard_stuff[mb].rx_dsps[dspno], _1)); +                .subscribe(boost::bind(&rx_dsp_core_200::issue_stream_command, _mbc[mb].rx_dsps[dspno], _1));          }          ////////////////////////////////////////////////////////////////          // create tx dsp control objects          //////////////////////////////////////////////////////////////// -        _mboard_stuff[mb].tx_dsp = tx_dsp_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), USRP2_TX_ASYNC_SID +        _mbc[mb].tx_dsp = tx_dsp_core_200::make( +            _mbc[mb].iface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), USRP2_TX_ASYNC_SID          );          _tree->access<double>(mb_path / "tick_rate") -            .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mboard_stuff[mb].tx_dsp, _1)); +            .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1));          _tree->create<double>(mb_path / "tx_dsps/0/rate/value") -            .subscribe_master(boost::bind(&tx_dsp_core_200::set_host_rate, _mboard_stuff[mb].tx_dsp, _1)) +            .subscribe_master(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));          _tree->create<double>(mb_path / "tx_dsps/0/freq/value") -            .subscribe_master(boost::bind(&tx_dsp_core_200::set_freq, _mboard_stuff[mb].tx_dsp, _1)); -        //TODO combine w/ codec shift +            .subscribe_master(boost::bind(&usrp2_impl::set_tx_dsp_freq, this, mb, _1)); +          //setup dsp flow control -        const double ups_per_sec = device_args[mb].cast<double>("ups_per_sec", 20); -        const size_t send_frame_size = _mboard_stuff[mb].dsp_xports.front()->get_send_frame_size(); -        const double ups_per_fifo = device_args[mb].cast<double>("ups_per_fifo", 8.0); -        _mboard_stuff[mb].tx_dsp->set_updates( +        const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20); +        const size_t send_frame_size = _mbc[mb].dsp_xports.front()->get_send_frame_size(); +        const double ups_per_fifo = device_args_i.cast<double>("ups_per_fifo", 8.0); +        _mbc[mb].tx_dsp->set_updates(              (ups_per_sec > 0.0)? size_t(100e6/*approx tick rate*//ups_per_sec) : 0,              (ups_per_fifo > 0.0)? size_t(USRP2_SRAM_BYTES/ups_per_fifo/send_frame_size) : 0          ); @@ -481,17 +469,27 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          time64_rb_bases.rb_ticks_imm = 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; -        _mboard_stuff[mb].time64 = time64_core_200::make( -            _mboard_stuff[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles +        _mbc[mb].time64 = time64_core_200::make( +            _mbc[mb].iface, U2_REG_SR_ADDR(SR_TIME64), time64_rb_bases, mimo_clock_sync_delay_cycles          );          _tree->access<double>(mb_path / "tick_rate") -            .subscribe(boost::bind(&time64_core_200::set_tick_rate, _mboard_stuff[mb].time64, _1)); +            .subscribe(boost::bind(&time64_core_200::set_tick_rate, _mbc[mb].time64, _1));          _tree->create<time_spec_t>(mb_path / "time/now") -            .publish(boost::bind(&time64_core_200::get_time_now, _mboard_stuff[mb].time64)) -            .subscribe(boost::bind(&time64_core_200::set_time_now, _mboard_stuff[mb].time64, _1)); +            .publish(boost::bind(&time64_core_200::get_time_now, _mbc[mb].time64)) +            .subscribe(boost::bind(&time64_core_200::set_time_now, _mbc[mb].time64, _1));          _tree->create<time_spec_t>(mb_path / "time/pps") -            .publish(boost::bind(&time64_core_200::get_time_last_pps, _mboard_stuff[mb].time64)) -            .subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mboard_stuff[mb].time64, _1)); +            .publish(boost::bind(&time64_core_200::get_time_last_pps, _mbc[mb].time64)) +            .subscribe(boost::bind(&time64_core_200::set_time_next_pps, _mbc[mb].time64, _1)); +        //setup time source props +        _tree->create<std::string>(mb_path / "time_source/value") +            .subscribe(boost::bind(&time64_core_200::set_time_source, _mbc[mb].time64, _1)); +        _tree->create<std::vector<std::string> >(mb_path / "time_source/options") +            .publish(boost::bind(&time64_core_200::get_time_sources, _mbc[mb].time64)); +        //setup reference source props +        _tree->create<std::string>(mb_path / "ref_source/value") +            .subscribe(boost::bind(&usrp2_impl::update_ref_source, this, mb, _1)); +        static const std::vector<std::string> ref_sources = boost::assign::list_of("internal")("sma")("mimo"); +        _tree->create<std::vector<std::string> >(mb_path / "ref_source/options").set(ref_sources);          ////////////////////////////////////////////////////////////////          // create dboard control objects @@ -499,9 +497,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){          //read the dboard eeprom to extract the dboard ids          dboard_eeprom_t rx_db_eeprom, tx_db_eeprom, gdb_eeprom; -        rx_db_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_RX_DB); -        tx_db_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_TX_DB); -        gdb_eeprom.load(*_mboard_stuff[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5); +        rx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB); +        tx_db_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB); +        gdb_eeprom.load(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);          //create the properties and register subscribers          _tree->create<dboard_eeprom_t>(mb_path / "dboards/A/rx_eeprom") @@ -512,23 +510,23 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){              .subscribe(boost::bind(&usrp2_impl::set_db_eeprom, this, mb, "gdb", _1));          //create a new dboard interface and manager -        _mboard_stuff[mb].dboard_iface = make_usrp2_dboard_iface(_mboard_stuff[mb].iface, _mboard_stuff[mb].clock); -        _tree->create<dboard_iface::sptr>(mb_path / "dboards/A/iface").set(_mboard_stuff[mb].dboard_iface); -        _mboard_stuff[mb].dboard_manager = dboard_manager::make( +        _mbc[mb].dboard_iface = make_usrp2_dboard_iface(_mbc[mb].iface, _mbc[mb].clock); +        _tree->create<dboard_iface::sptr>(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, -            _mboard_stuff[mb].dboard_iface +            _mbc[mb].dboard_iface          ); -        BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].dboard_manager->get_rx_subdev_names()){ +        BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_rx_subdev_names()){              dboard_manager::populate_prop_tree_from_subdev(                  _tree, mb_path / "dboards/A/rx_frontends" / name, -                _mboard_stuff[mb].dboard_manager->get_rx_subdev(name) +                _mbc[mb].dboard_manager->get_rx_subdev(name)              );          } -        BOOST_FOREACH(const std::string &name, _mboard_stuff[mb].dboard_manager->get_tx_subdev_names()){ +        BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_tx_subdev_names()){              dboard_manager::populate_prop_tree_from_subdev(                  _tree, mb_path / "dboards/A/tx_frontends" / name, -                _mboard_stuff[mb].dboard_manager->get_tx_subdev(name) +                _mbc[mb].dboard_manager->get_tx_subdev(name)              );          }      } @@ -537,36 +535,114 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){      this->io_init();      //do some post-init tasks -    for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){ -        _tree->access<double>(str(boost::format("/mboards/%u/tick_rate") % mb)).update(); -        _tree->access<subdev_spec_t>(str(boost::format("/mboards/%u/rx_subdev_spec") % mb)).set(subdev_spec_t()); -        _tree->access<subdev_spec_t>(str(boost::format("/mboards/%u/tx_subdev_spec") % mb)).set(subdev_spec_t()); +    BOOST_FOREACH(const std::string &mb, _mbc.keys()){ +        property_tree::path_type root = "/mboards/" + mb; +        _tree->access<double>(root / "tick_rate").update(); +        _tree->access<subdev_spec_t>(root / "rx_subdev_spec").set(subdev_spec_t()); +        _tree->access<subdev_spec_t>(root / "tx_subdev_spec").set(subdev_spec_t()); +        _tree->access<std::string>(root / "ref_source/value").set("internal"); +        _tree->access<std::string>(root / "time_source/value").set("none"); + +        //GPS installed: use external ref, time, and init time spec +        if (_mbc[mb].gps.get() != NULL){ +            _tree->access<std::string>(root / "time_source/value").set("sma"); +            _tree->access<std::string>(root / "ref_source/value").set("sma"); +            _mbc[mb].time64->set_time_next_pps(time_spec_t(time_t(_mbc[mb].gps->get_sensor("gps_time").to_int()+1))); +        }      }  }  usrp2_impl::~usrp2_impl(void){UHD_SAFE_CALL( -    for (size_t mb = 0; mb < _mboard_stuff.size(); mb++){ -        _mboard_stuff[mb].tx_dsp->set_updates(0, 0); +    BOOST_FOREACH(const std::string &mb, _mbc.keys()){ +        _mbc[mb].tx_dsp->set_updates(0, 0);      }  )} -void usrp2_impl::set_mb_eeprom(const size_t which_mb, const uhd::usrp::mboard_eeprom_t &mb_eeprom){ -    mb_eeprom.commit(*(_mboard_stuff[which_mb].iface), mboard_eeprom_t::MAP_N100); +void usrp2_impl::set_mb_eeprom(const std::string &mb, const uhd::usrp::mboard_eeprom_t &mb_eeprom){ +    mb_eeprom.commit(*(_mbc[mb].iface), mboard_eeprom_t::MAP_N100);  } -void usrp2_impl::set_db_eeprom(const size_t which_mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom){ -    if (type == "rx") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_RX_DB); -    if (type == "tx") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_TX_DB); -    if (type == "gdb") db_eeprom.store(*_mboard_stuff[which_mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5); +void usrp2_impl::set_db_eeprom(const std::string &mb, const std::string &type, const uhd::usrp::dboard_eeprom_t &db_eeprom){ +    if (type == "rx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_RX_DB); +    if (type == "tx") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB); +    if (type == "gdb") db_eeprom.store(*_mbc[mb].iface, USRP2_I2C_ADDR_TX_DB ^ 5);  } -sensor_value_t usrp2_impl::get_mimo_locked(const size_t which_mb){ -    const bool lock = (_mboard_stuff[which_mb].iface->peek32(U2_REG_IRQ_RB) & (1<<10)) != 0; +sensor_value_t usrp2_impl::get_mimo_locked(const std::string &mb){ +    const bool lock = (_mbc[mb].iface->peek32(U2_REG_IRQ_RB) & (1<<10)) != 0;      return sensor_value_t("MIMO", lock, "locked", "unlocked");  } -sensor_value_t usrp2_impl::get_ref_locked(const size_t which_mb){ -    const bool lock = (_mboard_stuff[which_mb].iface->peek32(U2_REG_IRQ_RB) & (1<<11)) != 0; +sensor_value_t usrp2_impl::get_ref_locked(const std::string &mb){ +    const bool lock = (_mbc[mb].iface->peek32(U2_REG_IRQ_RB) & (1<<11)) != 0;      return sensor_value_t("Ref", lock, "locked", "unlocked");  } + +#include <boost/math/special_functions/round.hpp> +#include <boost/math/special_functions/sign.hpp> + +double usrp2_impl::set_tx_dsp_freq(const std::string &mb, const double freq_){ +    double new_freq = freq_; +    const double tick_rate = _tree->access<double>("/mboards/"+mb+"/tick_rate").get(); + +    //calculate the DAC shift (multiples of rate) +    const int sign = boost::math::sign(new_freq); +    const int zone = std::min(boost::math::iround(new_freq/tick_rate), 2); +    const double dac_shift = sign*zone*tick_rate; +    new_freq -= dac_shift; //update FPGA DSP target freq + +    //set the DAC shift (modulation mode) +    if (zone == 0) _mbc[mb].codec->set_tx_mod_mode(0); //no shift +    else _mbc[mb].codec->set_tx_mod_mode(sign*4/zone); //DAC interp = 4 + +    return _mbc[mb].tx_dsp->set_freq(new_freq) + dac_shift; //actual freq +} + +void usrp2_impl::update_ref_source(const std::string &mb, const std::string &source){ +    //clock source ref 10mhz +    switch(_mbc[mb].iface->get_rev()){ +    case usrp2_iface::USRP_N200: +    case usrp2_iface::USRP_N210: +    case usrp2_iface::USRP_N200_R4: +    case usrp2_iface::USRP_N210_R4: +        if (source == "internal")  _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x12); +        else if (source == "sma")  _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); +        else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); +        else throw uhd::value_error("unhandled clock configuration reference source: " + source); +        _mbc[mb].clock->enable_external_ref(true); //USRP2P has an internal 10MHz TCXO +        break; + +    case usrp2_iface::USRP2_REV3: +    case usrp2_iface::USRP2_REV4: +        if (source == "internal")  _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x10); +        else if (source == "sma")  _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x1C); +        else if (source == "mimo") _mbc[mb].iface->poke32(U2_REG_MISC_CTRL_CLOCK, 0x15); +        else throw uhd::value_error("unhandled clock configuration reference source: " + source); +        _mbc[mb].clock->enable_external_ref(source != "internal"); +        break; + +    case usrp2_iface::USRP_NXXX: break; +    } + +    //always drive the clock over serdes if not locking to it +    _mbc[mb].clock->enable_mimo_clock_out(source != "mimo"); + +    //set the mimo clock delay over the serdes +    if (source != "mimo"){ +        switch(_mbc[mb].iface->get_rev()){ +        case usrp2_iface::USRP_N200: +        case usrp2_iface::USRP_N210: +        case usrp2_iface::USRP_N200_R4: +        case usrp2_iface::USRP_N210_R4: +            _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp_n2xx); +            break; + +        case usrp2_iface::USRP2_REV4: +            _mbc[mb].clock->set_mimo_clock_delay(mimo_clock_delay_usrp2_rev4); +            break; + +        default: break; //not handled +        } +    } +} | 
