aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/n230/n230_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/n230/n230_impl.cpp')
-rw-r--r--host/lib/usrp/n230/n230_impl.cpp613
1 files changed, 0 insertions, 613 deletions
diff --git a/host/lib/usrp/n230/n230_impl.cpp b/host/lib/usrp/n230/n230_impl.cpp
deleted file mode 100644
index 854585ae2..000000000
--- a/host/lib/usrp/n230/n230_impl.cpp
+++ /dev/null
@@ -1,613 +0,0 @@
-//
-// Copyright 2014 Ettus Research LLC
-// Copyright 2018 Ettus Research, a National Instruments Company
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-#include "n230_impl.hpp"
-#include "n230_fw_ctrl_iface.hpp"
-#include "n230_defaults.h"
-#include "n230_fpga_defs.h"
-#include "n230_fw_defs.h"
-#include "n230_fw_host_iface.h"
-
-#include <uhdlib/usrp/common/validate_subdev_spec.hpp>
-
-#include <uhd/utils/static.hpp>
-#include <uhd/transport/if_addrs.hpp>
-#include <uhd/transport/udp_zero_copy.hpp>
-#include <uhd/usrp/subdev_spec.hpp>
-#include <uhd/utils/byteswap.hpp>
-#include <uhd/utils/log.hpp>
-
-#include <uhd/types/sensors.hpp>
-#include <uhd/types/ranges.hpp>
-#include <uhd/types/direction.hpp>
-#include <uhd/usrp/mboard_eeprom.hpp>
-#include <uhd/usrp/dboard_eeprom.hpp>
-#include <uhd/usrp/gps_ctrl.hpp>
-
-#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/bind.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/asio/ip/address_v4.hpp>
-#include <boost/asio.hpp> //used for htonl and ntohl
-#include <boost/make_shared.hpp>
-
-#include <chrono>
-#include <thread>
-
-namespace uhd { namespace usrp { namespace n230 {
-
-using namespace uhd::transport;
-namespace asio = boost::asio;
-
-//----------------------------------------------------------
-// Static device registration with framework
-//----------------------------------------------------------
-UHD_STATIC_BLOCK(register_n230_device)
-{
- device::register_device(&n230_impl::n230_find, &n230_impl::n230_make, device::USRP);
-}
-
-//----------------------------------------------------------
-// Device discovery
-//----------------------------------------------------------
-uhd::device_addrs_t n230_impl::n230_find(const uhd::device_addr_t &multi_dev_hint)
-{
- //handle the multi-device discovery
- device_addrs_t hints = separate_device_addr(multi_dev_hint);
- if (hints.size() > 1){
- device_addrs_t found_devices;
- std::string error_msg;
- for(const device_addr_t &hint_i: hints){
- device_addrs_t found_devices_i = n230_find(hint_i);
- if (found_devices_i.size() != 1) error_msg += str(boost::format(
- "Could not resolve device hint \"%s\" to a single device."
- ) % hint_i.to_string());
- else found_devices.push_back(found_devices_i[0]);
- }
- if (found_devices.empty()) return device_addrs_t();
- if (not error_msg.empty()) throw uhd::value_error(error_msg);
- return device_addrs_t(1, combine_device_addrs(found_devices));
- }
-
- //initialize the hint for a single device case
- UHD_ASSERT_THROW(hints.size() <= 1);
- hints.resize(1); //in case it was empty
- device_addr_t hint = hints[0];
- device_addrs_t n230_addrs;
-
- //return an empty list of addresses when type is set to non-n230
- if (hint.has_key("type") and hint["type"] != "n230") return n230_addrs;
-
- //Return an empty list of addresses when a resource is specified,
- //since a resource is intended for a different, non-networked, device.
- if (hint.has_key("resource")) return n230_addrs;
-
- //if no address was specified, send a broadcast on each interface
- if (not hint.has_key("addr")) {
- for(const if_addrs_t &if_addrs: get_if_addrs()) {
- //avoid the loopback device
- if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue;
-
- //create a new hint with this broadcast address
- device_addr_t new_hint = hint;
- new_hint["addr"] = if_addrs.bcast;
-
- //call discover with the new hint and append results
- device_addrs_t new_n230_addrs = n230_find(new_hint);
- n230_addrs.insert(n230_addrs.begin(),
- new_n230_addrs.begin(), new_n230_addrs.end()
- );
- }
- return n230_addrs;
- }
-
- std::vector<std::string> discovered_addrs =
- n230_fw_ctrl_iface::discover_devices(
- hint["addr"], BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT), N230_FW_PRODUCT_ID);
-
- for(const std::string& addr: discovered_addrs)
- {
- device_addr_t new_addr;
- new_addr["type"] = "n230";
- new_addr["addr"] = addr;
-
- //Attempt a simple 2-way communication with a connected socket.
- //Reason: Although the USRP will respond the broadcast above,
- //we may not be able to communicate directly (non-broadcast).
- udp_simple::sptr ctrl_xport = udp_simple::make_connected(new_addr["addr"], BOOST_STRINGIZE(N230_FW_COMMS_UDP_PORT));
-
- //Corner case: If two devices have the same IP but different MAC
- //addresses and are used back-to-back it takes a while for ARP tables
- //on the host to update in which period brodcasts will respond but
- //connected communication can fail. Retry the following call to allow
- //the stack to update
- size_t first_conn_retries = 10;
- n230_fw_ctrl_iface::sptr fw_ctrl;
- while (first_conn_retries > 0) {
- try {
- fw_ctrl = n230_fw_ctrl_iface::make(ctrl_xport, N230_FW_PRODUCT_ID, false /*verbose*/);
- break;
- } catch (uhd::io_error& ex) {
- std::this_thread::sleep_for(std::chrono::milliseconds(500));
- first_conn_retries--;
- }
- }
- if (first_conn_retries > 0) {
- uint32_t compat_reg = fw_ctrl->peek32(fw::reg_addr(fw::WB_SBRB_BASE, fw::RB_ZPU_COMPAT));
- if (fw::get_prod_num(compat_reg) == fw::PRODUCT_NUM) {
- if (!n230_resource_manager::is_device_claimed(fw_ctrl)) {
- //Not claimed by another process or host
- try {
- //Try to read the EEPROM to get the name and serial
- n230_eeprom_manager eeprom_mgr(new_addr["addr"]);
- const mboard_eeprom_t& eeprom = eeprom_mgr.get_mb_eeprom();
- new_addr["name"] = eeprom["name"];
- new_addr["serial"] = eeprom["serial"];
- }
- catch(const std::exception &)
- {
- //set these values as empty string so the device may still be found
- //and the filter's below can still operate on the discovered device
- new_addr["name"] = "";
- new_addr["serial"] = "";
- }
- //filter the discovered device below by matching optional keys
- if ((not hint.has_key("name") or hint["name"] == new_addr["name"]) and
- (not hint.has_key("serial") or hint["serial"] == new_addr["serial"]))
- {
- n230_addrs.push_back(new_addr);
- }
- }
- }
- }
- }
-
- return n230_addrs;
-}
-
-/***********************************************************************
- * Make
- **********************************************************************/
-device::sptr n230_impl::n230_make(const device_addr_t &device_addr)
-{
- return device::sptr(new n230_impl(device_addr));
-}
-
-/***********************************************************************
- * n230_impl::ctor
- **********************************************************************/
-n230_impl::n230_impl(const uhd::device_addr_t& dev_addr)
-{
- UHD_LOGGER_INFO("N230") << "N230 initialization sequence...";
- _dev_args.parse(dev_addr);
- _tree = uhd::property_tree::make();
-
- //TODO: Only supports one motherboard per device class.
- const fs_path mb_path = "/mboards/0";
-
- //Initialize addresses
- std::vector<std::string> ip_addrs(1, dev_addr["addr"]);
- if (dev_addr.has_key("second_addr")) {
- ip_addrs.push_back(dev_addr["second_addr"]);
- }
-
- //Read EEPROM and perform version checks before talking to HW
- _eeprom_mgr = boost::make_shared<n230_eeprom_manager>(ip_addrs[0]);
- const mboard_eeprom_t& mb_eeprom = _eeprom_mgr->get_mb_eeprom();
- bool recover_mb_eeprom = dev_addr.has_key("recover_mb_eeprom");
- if (recover_mb_eeprom) {
- UHD_LOGGER_WARNING("N230") << "UHD is operating in EEPROM Recovery Mode which disables hardware version "
- "checks.\nOperating in this mode may cause hardware damage and unstable "
- "radio performance!";
- }
- uint16_t hw_rev = boost::lexical_cast<uint16_t>(mb_eeprom["revision"]);
- uint16_t hw_rev_compat = boost::lexical_cast<uint16_t>(mb_eeprom["revision_compat"]);
- if (not recover_mb_eeprom) {
- if (hw_rev_compat > N230_HW_REVISION_COMPAT) {
- throw uhd::runtime_error(str(boost::format(
- "Hardware is too new for this software. Please upgrade to a driver that supports hardware revision %d.")
- % hw_rev));
- }
- }
-
- //Initialize all subsystems
- _resource_mgr = boost::make_shared<n230_resource_manager>(ip_addrs, _dev_args.get_safe_mode());
- _stream_mgr = boost::make_shared<n230_stream_manager>(_dev_args, _resource_mgr, _tree);
-
- //Build property tree
- _initialize_property_tree(mb_path);
-
- //Debug loopback mode
- switch(_dev_args.get_loopback_mode()) {
- case n230_device_args_t::LOOPBACK_RADIO:
- UHD_LOGGER_INFO("N230") << "DEBUG: Running in TX->RX Radio loopback mode.";
- _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_RADIO);
- break;
- case n230_device_args_t::LOOPBACK_CODEC:
- UHD_LOGGER_INFO("N230") << "DEBUG: Running in TX->RX CODEC loopback mode.";
- _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_CODEC);
- break;
- default:
- _resource_mgr->get_frontend_ctrl().set_self_test_mode(LOOPBACK_DISABLED);
- break;
- }
-}
-
-/***********************************************************************
- * n230_impl::dtor
- **********************************************************************/
-n230_impl::~n230_impl()
-{
- _stream_mgr.reset();
- _eeprom_mgr.reset();
- _resource_mgr.reset();
- _tree.reset();
-}
-
-/***********************************************************************
- * n230_impl::get_rx_stream
- **********************************************************************/
-rx_streamer::sptr n230_impl::get_rx_stream(const uhd::stream_args_t &args)
-{
- return _stream_mgr->get_rx_stream(args);
-}
-
-/***********************************************************************
- * n230_impl::get_tx_stream
- **********************************************************************/
-tx_streamer::sptr n230_impl::get_tx_stream(const uhd::stream_args_t &args)
-{
- return _stream_mgr->get_tx_stream(args);
-}
-
-/***********************************************************************
- * n230_impl::recv_async_msg
- **********************************************************************/
-bool n230_impl::recv_async_msg(uhd::async_metadata_t &async_metadata, double timeout)
-{
- return _stream_mgr->recv_async_msg(async_metadata, timeout);
-}
-
-/***********************************************************************
- * _initialize_property_tree
- **********************************************************************/
-void n230_impl::_initialize_property_tree(const fs_path& mb_path)
-{
- //------------------------------------------------------------------
- // General info
- //------------------------------------------------------------------
- _tree->create<std::string>("/name").set("N230 Device");
-
- _tree->create<std::string>(mb_path / "name").set("N230");
- _tree->create<std::string>(mb_path / "codename").set("N230");
- _tree->create<std::string>(mb_path / "dboards").set("none"); //No dboards.
-
- _tree->create<std::string>(mb_path / "fw_version").set(str(boost::format("%u.%u")
- % _resource_mgr->get_version(FIRMWARE, COMPAT_MAJOR)
- % _resource_mgr->get_version(FIRMWARE, COMPAT_MINOR)));
- _tree->create<std::string>(mb_path / "fw_version_hash").set(str(boost::format("%s")
- % _resource_mgr->get_version_hash(FIRMWARE)));
- _tree->create<std::string>(mb_path / "fpga_version").set(str(boost::format("%u.%u")
- % _resource_mgr->get_version(FPGA, COMPAT_MAJOR)
- % _resource_mgr->get_version(FPGA, COMPAT_MINOR)));
- _tree->create<std::string>(mb_path / "fpga_version_hash").set(str(boost::format("%s")
- % _resource_mgr->get_version_hash(FPGA)));
-
- _tree->create<double>(mb_path / "link_max_rate").set(_resource_mgr->get_max_link_rate());
-
- //------------------------------------------------------------------
- // EEPROM
- //------------------------------------------------------------------
- _tree->create<mboard_eeprom_t>(mb_path / "eeprom")
- .set(_eeprom_mgr->get_mb_eeprom()) //Set first...
- .add_coerced_subscriber(boost::bind(&n230_eeprom_manager::write_mb_eeprom, _eeprom_mgr, _1)); //..then enable writer
-
- //------------------------------------------------------------------
- // Create codec nodes
- //------------------------------------------------------------------
- const fs_path rx_codec_path = mb_path / ("rx_codecs") / "A";
- _tree->create<std::string>(rx_codec_path / "name")
- .set("N230 RX dual ADC");
- _tree->create<int>(rx_codec_path / "gains"); //Empty because gains are in frontend
-
- const fs_path tx_codec_path = mb_path / ("tx_codecs") / "A";
- _tree->create<std::string>(tx_codec_path / "name")
- .set("N230 TX dual DAC");
- _tree->create<int>(tx_codec_path / "gains"); //Empty because gains are in frontend
-
- //------------------------------------------------------------------
- // Create clock and time control nodes
- //------------------------------------------------------------------
- _tree->create<double>(mb_path / "tick_rate")
- .set_coercer(boost::bind(&n230_clk_pps_ctrl::set_tick_rate, _resource_mgr->get_clk_pps_ctrl_sptr(), _1))
- .set_publisher(boost::bind(&n230_clk_pps_ctrl::get_tick_rate, _resource_mgr->get_clk_pps_ctrl_sptr()))
- .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_tick_rate, _stream_mgr, _1));
-
- //Register time now and pps onto available radio cores
- //radio0 is the master
- _tree->create<time_spec_t>(mb_path / "time" / "cmd");
- _tree->create<time_spec_t>(mb_path / "time" / "now")
- .set_publisher(boost::bind(&time_core_3000::get_time_now, _resource_mgr->get_radio(0).time));
- _tree->create<time_spec_t>(mb_path / "time" / "pps")
- .set_publisher(boost::bind(&time_core_3000::get_time_last_pps, _resource_mgr->get_radio(0).time));
-
- //Setup time source props
- _tree->create<std::string>(mb_path / "time_source" / "value")
- .add_coerced_subscriber(boost::bind(&n230_impl::_check_time_source, this, _1))
- .add_coerced_subscriber(boost::bind(&n230_clk_pps_ctrl::set_pps_source, _resource_mgr->get_clk_pps_ctrl_sptr(), _1))
- .set(n230::DEFAULT_TIME_SRC);
- const std::vector<std::string> time_sources{"none", "external", "gpsdo"};
- _tree->create<std::vector<std::string> >(mb_path / "time_source" / "options")
- .set(time_sources);
-
- //Setup reference source props
- _tree->create<std::string>(mb_path / "clock_source" / "value")
- .add_coerced_subscriber(boost::bind(&n230_impl::_check_clock_source, this, _1))
- .add_coerced_subscriber(boost::bind(&n230_clk_pps_ctrl::set_clock_source, _resource_mgr->get_clk_pps_ctrl_sptr(), _1))
- .set(n230::DEFAULT_CLOCK_SRC);
- const std::vector<std::string> clock_sources{"internal", "external", "gpsdo"};
- _tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options")
- .set(clock_sources);
- _tree->create<sensor_value_t>(mb_path / "sensors" / "ref_locked")
- .set_publisher(boost::bind(&n230_clk_pps_ctrl::get_ref_locked, _resource_mgr->get_clk_pps_ctrl_sptr()));
-
- //------------------------------------------------------------------
- // Create frontend mapping
- //------------------------------------------------------------------
- _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
- .set(subdev_spec_t())
- .add_coerced_subscriber(boost::bind(&n230_impl::_update_rx_subdev_spec, this, _1));
- _tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec")
- .set(subdev_spec_t())
- .add_coerced_subscriber(boost::bind(&n230_impl::_update_tx_subdev_spec, this, _1));
-
- //------------------------------------------------------------------
- // Create a fake dboard to put frontends in
- //------------------------------------------------------------------
- //For completeness we give it a fake EEPROM as well
- dboard_eeprom_t db_eeprom; //Default state: ID is 0xffff, Version and serial empty
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "rx_eeprom").set(db_eeprom);
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "tx_eeprom").set(db_eeprom);
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "gdb_eeprom").set(db_eeprom);
-
- //------------------------------------------------------------------
- // Create radio specific nodes
- //------------------------------------------------------------------
- for (size_t radio_instance = 0; radio_instance < fpga::NUM_RADIOS; radio_instance++) {
- _initialize_radio_properties(mb_path, radio_instance);
- }
- //Update tick rate on newly created radio objects
- _tree->access<double>(mb_path / "tick_rate").set(_dev_args.get_master_clock_rate());
-
- //------------------------------------------------------------------
- // Initialize subdev specs
- //------------------------------------------------------------------
- subdev_spec_t rx_spec, tx_spec;
- for(const std::string &fe: _tree->list(mb_path / "dboards" / "A" / "rx_frontends"))
- {
- rx_spec.push_back(subdev_spec_pair_t("A", fe));
- }
- for(const std::string &fe: _tree->list(mb_path / "dboards" / "A" / "tx_frontends"))
- {
- tx_spec.push_back(subdev_spec_pair_t("A", fe));
- }
- _tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_spec);
- _tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec);
-
- //------------------------------------------------------------------
- // MiniSAS GPIO
- //------------------------------------------------------------------
- for(const usrp::gpio_atr::gpio_attr_map_t::value_type attr: usrp::gpio_atr::gpio_attr_map) {
- switch (attr.first){
- case usrp::gpio_atr::GPIO_SRC:
- case usrp::gpio_atr::GPIO_CTRL:
- _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP0" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)));
- _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP1" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)));
- break;
- case usrp::gpio_atr::GPIO_DDR:
- _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP0" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)))
- .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){
- uint32_t val = 0;
- for(size_t i = 0 ; i < str_val.size() ; i++){
- val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i;
- }
- _resource_mgr->get_minisas_gpio_ctrl_sptr(0)->set_gpio_attr(attr.first, val);
- });
- _tree->create<std::vector<std::string>>(mb_path / "gpio" / "FP1" / attr.second)
- .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first)))
- .add_coerced_subscriber([this, attr](const std::vector<std::string> str_val){
- uint32_t val = 0;
- for(size_t i = 0 ; i < str_val.size() ; i++){
- val += usrp::gpio_atr::gpio_attr_value_pair.at(attr.second).at(str_val[i])<<i;
- }
- _resource_mgr->get_minisas_gpio_ctrl_sptr(1)->set_gpio_attr(attr.first, val);
- });
- break;
- case usrp::gpio_atr::GPIO_OUT:
- _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / attr.second)
- .set(0)
- .add_coerced_subscriber([this, attr](const uint32_t val){
- _resource_mgr->get_minisas_gpio_ctrl_sptr(0)->set_gpio_attr(attr.first, val);
- });
- _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / attr.second)
- .set(0)
- .add_coerced_subscriber([this, attr](const uint32_t val){
- _resource_mgr->get_minisas_gpio_ctrl_sptr(1)->set_gpio_attr(attr.first, val);
- });
- break;
- case usrp::gpio_atr::GPIO_READBACK:
- _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / "READBACK")
- .set_publisher(boost::bind(&gpio_atr::gpio_atr_3000::read_gpio, _resource_mgr->get_minisas_gpio_ctrl_sptr(0)));
- _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / "READBACK")
- .set_publisher(boost::bind(&gpio_atr::gpio_atr_3000::read_gpio, _resource_mgr->get_minisas_gpio_ctrl_sptr(1)));
- break;
- default:
- _tree->create<uint32_t>(mb_path / "gpio" / "FP0" / attr.second)
- .set(0);
- _tree->create<uint32_t>(mb_path / "gpio" / "FP1" / attr.second)
- .set(0);
- break;
- }
- }
- //------------------------------------------------------------------
- // GPSDO sensors
- //------------------------------------------------------------------
- if (_resource_mgr->is_gpsdo_present()) {
- uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl();
- for(const std::string &name: gps_ctrl->get_sensors())
- {
- _tree->create<sensor_value_t>(mb_path / "sensors" / name)
- .set_publisher(boost::bind(&gps_ctrl::get_sensor, gps_ctrl, name));
- }
- }
-}
-
-/***********************************************************************
- * _initialize_radio_properties
- **********************************************************************/
-void n230_impl::_initialize_radio_properties(const fs_path& mb_path, size_t instance)
-{
- radio_resource_t& perif = _resource_mgr->get_radio(instance);
-
- //Time
- _tree->access<time_spec_t>(mb_path / "time" / "cmd")
- .add_coerced_subscriber(boost::bind(&radio_ctrl_core_3000::set_time, perif.ctrl, _1));
- _tree->access<double>(mb_path / "tick_rate")
- .add_coerced_subscriber(boost::bind(&radio_ctrl_core_3000::set_tick_rate, perif.ctrl, _1));
- _tree->access<time_spec_t>(mb_path / "time" / "now")
- .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_now, perif.time, _1));
- _tree->access<time_spec_t>(mb_path / "time" / "pps")
- .add_coerced_subscriber(boost::bind(&time_core_3000::set_time_next_pps, perif.time, _1));
-
- //RX DSP
- _tree->access<double>(mb_path / "tick_rate")
- .add_coerced_subscriber(boost::bind(&rx_vita_core_3000::set_tick_rate, perif.framer, _1))
- .add_coerced_subscriber(boost::bind(&rx_dsp_core_3000::set_tick_rate, perif.ddc, _1));
- const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % instance);
- _tree->create<meta_range_t>(rx_dsp_path / "rate" / "range")
- .set_publisher(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc));
- _tree->create<double>(rx_dsp_path / "rate" / "value")
- .set_coercer(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1))
- .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_rx_samp_rate, _stream_mgr, instance, _1))
- .set(n230::DEFAULT_RX_SAMP_RATE);
- _tree->create<double>(rx_dsp_path / "freq" / "value")
- .set_coercer(boost::bind(&rx_dsp_core_3000::set_freq, perif.ddc, _1))
- .set(n230::DEFAULT_DDC_FREQ);
- _tree->create<meta_range_t>(rx_dsp_path / "freq" / "range")
- .set_publisher(boost::bind(&rx_dsp_core_3000::get_freq_range, perif.ddc));
- _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd")
- .add_coerced_subscriber(boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1));
-
- //TX DSP
- _tree->access<double>(mb_path / "tick_rate")
- .add_coerced_subscriber(boost::bind(&tx_dsp_core_3000::set_tick_rate, perif.duc, _1));
- const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % instance);
- _tree->create<meta_range_t>(tx_dsp_path / "rate" / "range")
- .set_publisher(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc));
- _tree->create<double>(tx_dsp_path / "rate" / "value")
- .set_coercer(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1))
- .add_coerced_subscriber(boost::bind(&n230_stream_manager::update_tx_samp_rate, _stream_mgr, instance, _1))
- .set(n230::DEFAULT_TX_SAMP_RATE);
- _tree->create<double>(tx_dsp_path / "freq" / "value")
- .set_coercer(boost::bind(&tx_dsp_core_3000::set_freq, perif.duc, _1))
- .set(n230::DEFAULT_DUC_FREQ);
- _tree->create<meta_range_t>(tx_dsp_path / "freq" / "range")
- .set_publisher(boost::bind(&tx_dsp_core_3000::get_freq_range, perif.duc));
-
- //RF Frontend Interfacing
- for (direction_t direction : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) {
- const std::string dir_str = (direction == RX_DIRECTION) ? "rx" : "tx";
- const std::string key = boost::to_upper_copy(dir_str) + str(boost::format("%u") % (instance + 1));
- const fs_path rf_fe_path = mb_path / "dboards" / "A" / (dir_str + "_frontends") / ((instance==0)?"A":"B");
-
- //CODEC subtree
- _resource_mgr->get_codec_mgr().populate_frontend_subtree(_tree->subtree(rf_fe_path), key, direction);
-
- //User settings
- _tree->create<uhd::wb_iface::sptr>(rf_fe_path / "user_settings" / "iface")
- .set(perif.user_settings);
-
- //Setup antenna stuff
- if (key[0] == 'R') {
- _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options")
- .set({"TX/RX", "RX2"});
- _tree->create<std::string>(rf_fe_path / "antenna" / "value")
- .add_coerced_subscriber(boost::bind(&n230_frontend_ctrl::set_antenna_sel, _resource_mgr->get_frontend_ctrl_sptr(), instance, _1))
- .set("RX2");
- }
- if (key[0] == 'T') {
- _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options")
- .set({"TX/RX"});
- _tree->create<std::string>(rf_fe_path / "antenna" / "value")
- .set("TX/RX");
- }
- }
-}
-
-void n230_impl::_update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec)
-{
- //sanity checking
- if (spec.size()) validate_subdev_spec(_tree, spec, "rx");
- UHD_ASSERT_THROW(spec.size() <= fpga::NUM_RADIOS);
-
- if (spec.size() > 0) {
- UHD_ASSERT_THROW(spec[0].db_name == "A");
- UHD_ASSERT_THROW(spec[0].sd_name == "A");
- }
- if (spec.size() > 1) {
- //TODO we can support swapping at a later date, only this combo is supported
- UHD_ASSERT_THROW(spec[1].db_name == "A");
- UHD_ASSERT_THROW(spec[1].sd_name == "B");
- }
-
- _stream_mgr->update_stream_states();
-}
-
-void n230_impl::_update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec)
-{
- //sanity checking
- if (spec.size()) validate_subdev_spec(_tree, spec, "tx");
- UHD_ASSERT_THROW(spec.size() <= fpga::NUM_RADIOS);
-
- if (spec.size() > 0) {
- UHD_ASSERT_THROW(spec[0].db_name == "A");
- UHD_ASSERT_THROW(spec[0].sd_name == "A");
- }
- if (spec.size() > 1) {
- //TODO we can support swapping at a later date, only this combo is supported
- UHD_ASSERT_THROW(spec[1].db_name == "A");
- UHD_ASSERT_THROW(spec[1].sd_name == "B");
- }
-
- _stream_mgr->update_stream_states();
-}
-
-void n230_impl::_check_time_source(std::string source)
-{
- if (source == "gpsdo")
- {
- uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl();
- if (not (gps_ctrl and gps_ctrl->gps_detected()))
- throw uhd::runtime_error("GPSDO time source not available");
- }
-}
-
-void n230_impl::_check_clock_source(std::string source)
-{
- if (source == "gpsdo")
- {
- uhd::gps_ctrl::sptr gps_ctrl = _resource_mgr->get_gps_ctrl();
- if (not (gps_ctrl and gps_ctrl->gps_detected()))
- throw uhd::runtime_error("GPSDO clock source not available");
- }
-}
-
-}}} //namespace