diff options
Diffstat (limited to 'host')
54 files changed, 1490 insertions, 6142 deletions
diff --git a/host/include/uhd/rfnoc/blocks/radio_e3xx.xml b/host/include/uhd/rfnoc/blocks/radio_e31x.xml index aece593a5..0635e397c 100644 --- a/host/include/uhd/rfnoc/blocks/radio_e3xx.xml +++ b/host/include/uhd/rfnoc/blocks/radio_e31x.xml @@ -1,11 +1,11 @@  <!--This defines one NoC-Block.-->  <nocblock> -  <name>Radio (E3XX)</name> +  <name>Radio (E31X)</name>    <blockname>Radio</blockname> -  <key>E3XXRadio</key> +  <key>E31XRadio</key>    <!--There can be several of these:-->    <ids> -    <id revision="0">12AD100000000000</id> +    <id revision="0">12AD100000003310</id>    </ids>    <!-- Registers -->    <registers> diff --git a/host/include/uhd/rfnoc/blocks/radio_neon.xml b/host/include/uhd/rfnoc/blocks/radio_e320.xml index 01f286324..01f286324 100644 --- a/host/include/uhd/rfnoc/blocks/radio_neon.xml +++ b/host/include/uhd/rfnoc/blocks/radio_e320.xml diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 85e07c242..b171cbfef 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -69,7 +69,6 @@ LIBUHD_REGISTER_COMPONENT("GPSD" ENABLE_GPSD OFF "ENABLE_LIBUHD;ENABLE_GPSD;LIBG  # Devices  LIBUHD_REGISTER_COMPONENT("B100" ENABLE_B100 ON "ENABLE_LIBUHD;ENABLE_USB" OFF OFF)  LIBUHD_REGISTER_COMPONENT("B200" ENABLE_B200 ON "ENABLE_LIBUHD;ENABLE_USB" OFF OFF) -LIBUHD_REGISTER_COMPONENT("E300" ENABLE_E300 OFF "ENABLE_LIBUHD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("USRP1" ENABLE_USRP1 ON "ENABLE_LIBUHD;ENABLE_USB" OFF OFF)  LIBUHD_REGISTER_COMPONENT("USRP2" ENABLE_USRP2 ON "ENABLE_LIBUHD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("X300" ENABLE_X300 ON "ENABLE_LIBUHD" OFF OFF) @@ -78,6 +77,7 @@ LIBUHD_REGISTER_COMPONENT("MPMD" ENABLE_MPMD ON "ENABLE_LIBUHD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("N300" ENABLE_N300 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("N320" ENABLE_N320 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("E320" ENABLE_E320 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF) +LIBUHD_REGISTER_COMPONENT("E300" ENABLE_E300 ON "ENABLE_LIBUHD;ENABLE_MPMD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("OctoClock" ENABLE_OCTOCLOCK ON "ENABLE_LIBUHD" OFF OFF)  LIBUHD_REGISTER_COMPONENT("DPDK" ENABLE_DPDK ON "ENABLE_MPMD;DPDK_FOUND" OFF OFF) diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 7f457d66a..6df37c2cf 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -46,7 +46,6 @@ INCLUDE_SUBDIRECTORY(mpmd)  INCLUDE_SUBDIRECTORY(usrp1)  INCLUDE_SUBDIRECTORY(usrp2)  INCLUDE_SUBDIRECTORY(b100) -INCLUDE_SUBDIRECTORY(e300)  INCLUDE_SUBDIRECTORY(x300)  INCLUDE_SUBDIRECTORY(b200)  INCLUDE_SUBDIRECTORY(n230) diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index f0e10871e..e12519c36 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1916,7 +1916,7 @@ double ad9361_device_t::set_clock_rate(const double req_rate)  /* This function returns the RX / TX rate between AD9361 and the FPGA.   */ -double ad9361_device_t::get_clock_rate() +double ad9361_device_t::get_clock_rate() const  {      return _baseband_bw;  } diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 57f71193f..96a105438 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -162,7 +162,7 @@ public:      void set_io_iface(ad9361_io::sptr io_iface);      /* Get the current clock rate. */ -    double get_clock_rate(); +    double get_clock_rate() const;      /* This function sets the RX / TX rate between AD9361 and the FPGA, and       * thus determines the interpolation / decimation required in the FPGA to diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 5328fcc90..8ee79103f 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -31,12 +31,6 @@ if(ENABLE_X300 OR ENABLE_USRP1 OR ENABLE_USRP2 OR ENABLE_B100)      )  endif(ENABLE_X300 OR ENABLE_USRP1 OR ENABLE_USRP2 OR ENABLE_B100) -if(ENABLE_E300) -    LIBUHD_APPEND_SOURCES( -        ${CMAKE_CURRENT_SOURCE_DIR}/db_e3x0.cpp -    ) -endif(ENABLE_E300) -  if(ENABLE_X300)      LIBUHD_APPEND_SOURCES(          ${CMAKE_CURRENT_SOURCE_DIR}/twinrx/twinrx_ctrl.cpp @@ -46,6 +40,9 @@ if(ENABLE_X300)      )  endif(ENABLE_X300) +if(ENABLE_E300 OR ENABLE_E320) +    INCLUDE_SUBDIRECTORY(e3xx) +endif(ENABLE_E300 OR ENABLE_E320)  if(ENABLE_N300)      INCLUDE_SUBDIRECTORY(magnesium)  endif(ENABLE_N300) @@ -55,5 +52,3 @@ endif(ENABLE_N320)  if(ENABLE_MPMD AND ENABLE_EISCAT)      INCLUDE_SUBDIRECTORY(eiscat)  endif(ENABLE_MPMD AND ENABLE_EISCAT) - -INCLUDE_SUBDIRECTORY(neon) diff --git a/host/lib/usrp/dboard/db_e3x0.cpp b/host/lib/usrp/dboard/db_e3x0.cpp deleted file mode 100644 index 2745ee3e8..000000000 --- a/host/lib/usrp/dboard/db_e3x0.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/utils/static.hpp> -#include <uhd/usrp/dboard_base.hpp> -#include <uhd/usrp/dboard_manager.hpp> - -namespace uhd { namespace usrp { - -/*********************************************************************** - * The E310 dboard - *   AD9361 Interface, thus two subdevs - **********************************************************************/ -class e310_dboard : public xcvr_dboard_base{ -public: -    e310_dboard(ctor_args_t args) : xcvr_dboard_base(args) {} - -    virtual ~e310_dboard(void) {} -}; - -/*********************************************************************** - * The E310 dboard - *   AD9364 Interface, thus one subdev - **********************************************************************/ -class e300_dboard : public xcvr_dboard_base{ -public: -    e300_dboard(ctor_args_t args) : xcvr_dboard_base(args) {} - -    virtual ~e300_dboard(void) {} -}; - -/*********************************************************************** - * Register the E310 dboards - **********************************************************************/ -static dboard_base::sptr make_e310_dboard(dboard_base::ctor_args_t args){ -    return dboard_base::sptr(new e310_dboard(args)); -} - -static dboard_base::sptr make_e300_dboard(dboard_base::ctor_args_t args){ -    return dboard_base::sptr(new e300_dboard(args)); -} - -}} // namespace - -using namespace uhd::usrp; - -UHD_STATIC_BLOCK(reg_e3x0_dboards){ -    dboard_manager::register_dboard(0x0110, &make_e310_dboard, "E310 MIMO XCVR"); -    dboard_manager::register_dboard(0x0100, &make_e300_dboard, "E300 SISO XCVR"); -} diff --git a/host/lib/usrp/dboard/e3xx/CMakeLists.txt b/host/lib/usrp/dboard/e3xx/CMakeLists.txt new file mode 100644 index 000000000..36376cd88 --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright 2018 Ettus Research, a National Instruments Company +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +IF(ENABLE_E300 OR ENABLE_E320) +        LIST(APPEND E3XX_SOURCES +        ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_radio_ctrl_impl.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_radio_ctrl_init.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_ad9361_iface.cpp +        ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_bands.cpp +    ) +    LIBUHD_APPEND_SOURCES(${E3XX_SOURCES}) +ENDIF(ENABLE_E300 OR ENABLE_E320) + +IF(ENABLE_E300) +        MESSAGE(STATUS "E300 Enabled") +        LIST(APPEND E300_SOURCES +        ${CMAKE_CURRENT_SOURCE_DIR}/e31x_radio_ctrl_impl.cpp +    ) +    LIBUHD_APPEND_SOURCES(${E300_SOURCES}) +ENDIF(ENABLE_E300) + +IF(ENABLE_E320) +        MESSAGE(STATUS "E320 Enabled") +        LIST(APPEND E320_SOURCES +        ${CMAKE_CURRENT_SOURCE_DIR}/e320_radio_ctrl_impl.cpp +    ) +    LIBUHD_APPEND_SOURCES(${E320_SOURCES}) +ENDIF(ENABLE_E320) diff --git a/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.cpp new file mode 100644 index 000000000..33565102c --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.cpp @@ -0,0 +1,302 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include "e31x_radio_ctrl_impl.hpp" +#include "e31x_regs.hpp" + +using namespace uhd; +using namespace uhd::usrp; +using namespace uhd::rfnoc; + +e31x_radio_ctrl_impl::e31x_radio_ctrl_impl( +    const make_args_t &make_args +): block_ctrl_base(make_args) +{ +    // Swap front ends for E310 +    _fe_swap = true; +} + +e31x_radio_ctrl_impl::~e31x_radio_ctrl_impl() +{ +    UHD_LOG_TRACE(unique_id(), "e31x_radio_ctrl_impl::dtor() "); +} + +/****************************************************************************** + * API Calls + *****************************************************************************/ +bool e31x_radio_ctrl_impl::check_radio_config() +{ +    // mapping of frontend to radio perif index +    static const size_t FE0 = 1; +    static const size_t FE1 = 0; +    const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); +    const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); + +    //setup the active chains in the codec +    if ((num_rx + num_tx) == 0) { +        // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock +        this->set_streaming_mode(true, false, true, false); +    } else { +        this->set_streaming_mode( +                _is_streamer_active(TX_DIRECTION, FE0), +                _is_streamer_active(TX_DIRECTION, FE1), +                _is_streamer_active(RX_DIRECTION, FE0), +                _is_streamer_active(RX_DIRECTION, FE1) +        ); +    } +    return true; +} + +/*  loopback_self_test checks the integrity of the FPGA->AD936x->FPGA sample interface. +    The AD936x is put in loopback mode that sends the TX data unchanged to the RX side. +    A test value is written to the codec_idle register in the TX side of the radio. +    The readback register is then used to capture the values on the TX and RX sides +    simultaneously for comparison. It is a reasonably effective test for AC timing +    since I/Q Ch0/Ch1 alternate over the same wires. Note, however, that it uses +    whatever timing is configured at the time the test is called rather than select +    worst case conditions to stress the interface. +    Note: This currently only tests 2R2T mode +*/ +void e31x_radio_ctrl_impl::loopback_self_test( +    std::function<void(uint32_t)> poker_functor, std::function<uint64_t()> peeker_functor) +{ +    // Save current rate before running this test +    const double current_rate = this->get_rate(); +    // Set 2R2T mode, stream on all channels +    this->set_streaming_mode(true, false, true, false); +    // Set maximum rate for 2R2T mode +    this->set_rate(30.72e6); +    // Put AD936x in loopback mode +    _ad9361->data_port_loopback(true); +    UHD_LOG_INFO(unique_id(), "Performing CODEC loopback test... "); +    size_t hash                     = size_t(time(NULL)); +    constexpr size_t loopback_count = 100; + +    // Allow some time for AD936x to enter loopback mode. +    // There is no clear statement in the documentation of how long it takes, +    // but UG-570 does say to "allow six ADC_CLK/64 clock cycles of flush time" +    // when leaving the TX or RX states.  That works out to ~75us at the +    // minimum clock rate of 5 MHz, which lines up with test results. +    // Sleeping 1ms is far more than enough. +    std::this_thread::sleep_for(std::chrono::milliseconds(1)); + +    for (size_t i = 0; i < loopback_count; i++) { +        // Create test word +        boost::hash_combine(hash, i); +        const uint32_t word32 = uint32_t(hash) & 0xfff0fff0; +        // const uint32_t word32 = 0xCA00C100; +        // Write test word to codec_idle idle register (on TX side) +        poker_functor(word32); + +        // Read back values - TX is lower 32-bits and RX is upper 32-bits +        const uint64_t rb_word64 = peeker_functor(); +        const uint32_t rb_tx     = uint32_t(rb_word64 >> 32); +        const uint32_t rb_rx     = uint32_t(rb_word64 & 0xffffffff); + +        // Compare TX and RX values to test word +        bool test_fail = word32 != rb_tx or word32 != rb_rx; +        if (test_fail) { +            UHD_LOG_WARNING(unique_id(), +                "CODEC loopback test failed! " +                    << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") +                           % word32 % rb_tx % rb_rx); +            throw uhd::runtime_error("CODEC loopback test failed."); +        } +    } +    UHD_LOG_INFO(unique_id(), "CODEC loopback test passed"); + +    // Zero out the idle data. +    poker_functor(0); + +    // Take AD936x out of loopback mode +    _ad9361->data_port_loopback(false); +    this->set_streaming_mode(true, false, true, false); +    // Switch back to current rate +    this->set_rate(current_rate); +} + + +uint32_t e31x_radio_ctrl_impl::get_tx_switches( +    const size_t chan, +    const double freq +) { +    UHD_LOG_TRACE(unique_id(), +        "Update all TX freq related switches. f=" << freq << " Hz, " +    ); + +    size_t fe_chan = _fe_swap ? (chan ? 0 : 1): chan; + +    auto tx_sw1 = TX_SW1_LB_2750;  // SW1 = 0 +    auto vctxrx_sw = VCTXRX_SW_OFF; +    auto tx_bias = (fe_chan == 0) ? TX1_BIAS_LB_ON: TX2_BIAS_LB_ON; + +    const auto band = e3xx_radio_ctrl_impl::map_freq_to_tx_band(freq); +    switch(band) { +    case tx_band::LB_80: +        tx_sw1 = TX_SW1_LB_80; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_160: +        tx_sw1 = TX_SW1_LB_160; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_225: +        tx_sw1 = TX_SW1_LB_225; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_400: +        tx_sw1 = TX_SW1_LB_400; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_575: +        tx_sw1 = TX_SW1_LB_575; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_1000: +        tx_sw1 = TX_SW1_LB_1000; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_1700: +        tx_sw1 = TX_SW1_LB_1700; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::LB_2750: +        tx_sw1 = TX_SW1_LB_2750; +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_TX_LB: VCTXRX2_SW_TX_LB; +        break; +    case tx_band::HB: +        tx_sw1 = TX_SW1_LB_80; +        vctxrx_sw = VCTXRX_SW_TX_HB; +        tx_bias = (fe_chan == 0) ? TX1_BIAS_HB_ON: TX2_BIAS_HB_ON; +        break; +    case tx_band::INVALID_BAND: +        UHD_LOG_ERROR(unique_id(), +            "Cannot map TX frequency to band: " << freq); +        UHD_THROW_INVALID_CODE_PATH(); +        break; +    } +    auto tx_regs = 0 | +             vctxrx_sw << VCTXRX_SW_SHIFT | +             tx_bias << TX_BIAS_SHIFT | +             tx_sw1 << TX_SW1_SHIFT; +    return tx_regs; +} + +uint32_t e31x_radio_ctrl_impl::get_rx_switches( +    const size_t chan, +    const double freq, +    const std::string &ant +){ +    UHD_LOG_TRACE(unique_id(), +        "Update all RX freq related switches. f=" << freq << " Hz, " +    ); + +    size_t fe_chan = _fe_swap ? (chan ? 0 : 1): chan; + +    // Default to OFF +    auto rx_sw1 = RX_SW1_OFF; +    auto rx_swc = RX_SWC_OFF; +    auto rx_swb = RX_SWB_OFF; +    auto vctxrx_sw = VCTXRX_SW_OFF; +    auto vcrx_sw = VCRX_SW_LB; +    if (ant == "TX/RX") { +        vctxrx_sw = (fe_chan == 0) ? VCTXRX1_SW_RX: VCTXRX2_SW_RX; +    } + +    UHD_LOG_INFO(unique_id(), "RX freq = " << freq); +    const auto band = e3xx_radio_ctrl_impl::map_freq_to_rx_band(freq); +    UHD_LOG_INFO(unique_id(), "RX band = " << int(band)); + +    switch(band) { +    case rx_band::LB_B2: +        rx_sw1 = RX_SW1_LB_B2; +        rx_swc = RX_SWC_LB_B2; +        rx_swb = RX_SWB_OFF; +        break; +    case rx_band::LB_B3: +        rx_sw1 = RX_SW1_LB_B3; +        rx_swc = RX_SWC_LB_B3; +        rx_swb = RX_SWB_OFF; +        break; +    case rx_band::LB_B4: +        rx_sw1 = RX_SW1_LB_B4; +        rx_swc = RX_SWC_LB_B4; +        rx_swb = RX_SWB_OFF; +        break; +    case rx_band::LB_B5: +        rx_sw1 = RX_SW1_LB_B5; +        rx_swc = RX_SWC_OFF; +        rx_swb = RX_SWB_LB_B5; +        break; +    case rx_band::LB_B6: +        rx_sw1 = RX_SW1_LB_B6; +        rx_swc = RX_SWC_OFF; +        rx_swb = RX_SWB_LB_B6; +        break; +    case rx_band::LB_B7: +        rx_sw1 = RX_SW1_LB_B7; +        rx_swc = RX_SWC_OFF; +        rx_swb = RX_SWB_LB_B7; +        break; +    case rx_band::HB: +        rx_sw1 = RX_SW1_OFF; +        rx_swc = RX_SWC_OFF; +        rx_swb = RX_SWB_OFF; +        vcrx_sw = VCRX_SW_HB; +        break; +    case rx_band::INVALID_BAND: +        UHD_LOG_ERROR(unique_id(), +            "Cannot map RX frequency to band: " << freq); +        UHD_THROW_INVALID_CODE_PATH(); +        break; +    } +    UHD_LOG_INFO(unique_id(), "RX SW1 = " << rx_sw1); +    UHD_LOG_INFO(unique_id(), "RX SWC = " << rx_swc); +    UHD_LOG_INFO(unique_id(), "RX SWB = " << rx_swb); +    UHD_LOG_INFO(unique_id(), "RX VCRX_SW = " << vcrx_sw); +    UHD_LOG_INFO(unique_id(), "RX VCTXRX_SW = " << vctxrx_sw); + +    auto rx_regs = 0 | +             vcrx_sw << VCRX_SW_SHIFT | +             vctxrx_sw << VCTXRX_SW_SHIFT | +             rx_swc << RX_SWC_SHIFT | +             rx_swb << RX_SWB_SHIFT | +             rx_sw1 << RX_SW1_SHIFT; +    return rx_regs; +} + +uint32_t e31x_radio_ctrl_impl::get_idle_switches() +{ +    uint32_t idle_regs = VCRX_SW_OFF << VCRX_SW_SHIFT | +                        VCTXRX_SW_OFF << VCTXRX_SW_SHIFT | +                        TX_BIAS_OFF << TX_BIAS_SHIFT | +                        RX_SWC_OFF << RX_SWC_SHIFT | +                        RX_SWB_OFF << RX_SWB_SHIFT | +                        RX_SW1_OFF << RX_SW1_SHIFT | +                        TX_SW1_LB_2750 << TX_SW1_SHIFT; +    return idle_regs; +} + +uint32_t e31x_radio_ctrl_impl::get_idle_led() +{ +    return 0; +} + +uint32_t e31x_radio_ctrl_impl::get_rx_led() +{ +    return 1 << LED_RX_RX_SHIFT; +} + +uint32_t e31x_radio_ctrl_impl::get_tx_led() +{ +    return 1 << LED_TXRX_TX_SHIFT; +} + +uint32_t e31x_radio_ctrl_impl::get_txrx_led() +{ +    return 1 << LED_TXRX_RX_SHIFT; +} +UHD_RFNOC_BLOCK_REGISTER(e31x_radio_ctrl, "E31XRadio"); diff --git a/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.hpp new file mode 100644 index 000000000..581a90c8e --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e31x_radio_ctrl_impl.hpp @@ -0,0 +1,144 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_E31X_RADIO_CTRL_IMPL_HPP +#define INCLUDED_LIBUHD_RFNOC_E31X_RADIO_CTRL_IMPL_HPP + +#include "e3xx_constants.hpp" +#include "e3xx_radio_ctrl_impl.hpp" + +namespace uhd { +    namespace rfnoc { + +/*! \brief Provide access to an E31X radio. + */ +class e31x_radio_ctrl_impl : public e3xx_radio_ctrl_impl +{ +public: +    /************************************************************************ +     * Structors +     ***********************************************************************/ +    e31x_radio_ctrl_impl( +        const make_args_t &make_args +    ); +    virtual ~e31x_radio_ctrl_impl(); + +protected: + +    /************************************************************************** +     * ATR/ Switches Types +     *************************************************************************/ + +    enum tx_sw1_t { +        TX_SW1_LB_80 = 7, +        TX_SW1_LB_160 = 6, +        TX_SW1_LB_225 = 5, +        TX_SW1_LB_400 = 4, +        TX_SW1_LB_575 = 3, +        TX_SW1_LB_1000 = 2, +        TX_SW1_LB_1700 = 1, +        TX_SW1_LB_2750 = 0, +        TX_SW1_HB_5850 = 7 +    }; + +    enum vctxrx_sw_t { +        VCTXRX_SW_TX_HB = 3, +        VCTXRX1_SW_TX_LB = 1, +        VCTXRX1_SW_RX = 2, +        VCTXRX2_SW_TX_LB = 2, +        VCTXRX2_SW_RX = 1, +        VCTXRX_SW_OFF = 0, +    }; + +    enum rx_sw1_t { +        RX_SW1_LB_B2 = 4, +        RX_SW1_LB_B3 = 2, +        RX_SW1_LB_B4 = 0, +        RX_SW1_LB_B5 = 1, +        RX_SW1_LB_B6 = 3, +        RX_SW1_LB_B7 = 5, +        RX_SW1_OFF = 7 +    }; + +    enum rx_swc_t { +        RX_SWC_LB_B2 = 2, +        RX_SWC_LB_B3 = 3, +        RX_SWC_LB_B4 = 1, +        RX_SWC_OFF = 0 +    }; + +    enum rx_swb_t { +        RX_SWB_LB_B5 = 2, +        RX_SWB_LB_B6 = 3, +        RX_SWB_LB_B7 = 1, +        RX_SWB_OFF = 0 +    }; + +    enum vcrx_sw_t { +        VCRX_SW_LB = 1, +        VCRX_SW_HB = 2, +        VCRX_SW_OFF = 0 //or 3 +    }; + +    // (TX_ENABLEB, TX_ENABLEA) +    enum tx_bias_t { +        TX1_BIAS_HB_ON = 1, +        TX1_BIAS_LB_ON = 2, +        TX2_BIAS_HB_ON = 1, +        TX2_BIAS_LB_ON = 2, +        TX_BIAS_OFF = 0 +    }; + +    /************************************************************************ +     * API calls +     ***********************************************************************/ +    virtual bool check_radio_config(); + +    const std::string get_default_timing_mode() +    { +        return TIMING_MODE_1R1T; +    }; + +    /*! Run a loopback self test. +     * +     * This will write data to the AD936x and read it back again. +     * If this test fails, it generally means the interface is broken, +     * so we assume it passes and throw otherwise. Running this requires +     * a core that we can peek and poke the loopback values into. +     * +     * \param iface An interface to the associated radio control core +     * \param iface The radio control core's address to write the loopback value +     * \param iface The radio control core's readback address to read back the returned +     * value +     * +     * \throws a uhd::runtime_error if the loopback value didn't match. +     */ +    void loopback_self_test(std::function<void(uint32_t)> poker_functor, +        std::function<uint64_t()> peeker_functor); + +    uint32_t get_rx_switches( +        const size_t chan, +        const double freq, +        const std::string &ant +    ); + +    uint32_t get_tx_switches( +        const size_t chan, +        const double freq +    ); + +    uint32_t get_idle_switches(); + +    uint32_t get_tx_led(); +    uint32_t get_rx_led(); +    uint32_t get_txrx_led(); +    uint32_t get_idle_led(); +}; /* class radio_ctrl_impl */ + +}} /* namespace uhd::rfnoc */ + +#endif /* INCLUDED_LIBUHD_RFNOC_E31X_RADIO_CTRL_IMPL_HPP */ +// vim: sw=4 et: diff --git a/host/lib/usrp/dboard/e3xx/e31x_regs.hpp b/host/lib/usrp/dboard/e3xx/e31x_regs.hpp new file mode 100644 index 000000000..15ce90743 --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e31x_regs.hpp @@ -0,0 +1,26 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_E31X_REGS_HPP +#define INCLUDED_E31X_REGS_HPP + +#include <uhd/config.hpp> +#include <cstdint> + +static const uint32_t VCRX_SW_SHIFT = 14; +static const uint32_t VCTXRX_SW_SHIFT  = 12; +static const uint32_t TX_BIAS_SHIFT  = 10; +static const uint32_t RX_SWC_SHIFT  = 8; +static const uint32_t RX_SWB_SHIFT  = 6; +static const uint32_t RX_SW1_SHIFT  = 3; +static const uint32_t TX_SW1_SHIFT  = 0; + +static const uint32_t LED_RX_RX_SHIFT  = 2; +static const uint32_t LED_TXRX_TX_SHIFT  = 1; +static const uint32_t LED_TXRX_RX_SHIFT  = 0; + +#endif /* INCLUDED_E31X_REGS_HPP */ + diff --git a/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.cpp new file mode 100644 index 000000000..c48cabc9c --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.cpp @@ -0,0 +1,272 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include "e320_radio_ctrl_impl.hpp" +#include "e320_regs.hpp" + +using namespace uhd; +using namespace uhd::usrp; +using namespace uhd::rfnoc; + +e320_radio_ctrl_impl::e320_radio_ctrl_impl(const make_args_t& make_args) +    : block_ctrl_base(make_args) +{ +    UHD_LOG_TRACE(unique_id(), "Entering e320_radio_ctrl_impl ctor..."); +    // Don't swap front ends for E320 +    _fe_swap = false; +} + +e320_radio_ctrl_impl::~e320_radio_ctrl_impl() +{ +    UHD_LOG_TRACE(unique_id(), "e320_radio_ctrl_impl::dtor() "); +} + +/****************************************************************************** + * API Calls + *****************************************************************************/ +bool e320_radio_ctrl_impl::check_radio_config() +{ +    // mapping of frontend to radio perif index +    static const size_t FE0 = 0; +    static const size_t FE1 = 1; +    const size_t num_rx = +        _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); +    const size_t num_tx = +        _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); + +    // setup the active chains in the codec +    if ((num_rx + num_tx) == 0) { +        // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock +        this->set_streaming_mode(true, false, true, false); +    } else { +        this->set_streaming_mode(_is_streamer_active(TX_DIRECTION, FE0), +            _is_streamer_active(TX_DIRECTION, FE1), +            _is_streamer_active(RX_DIRECTION, FE0), +            _is_streamer_active(RX_DIRECTION, FE1)); +    } +    return true; +} + +/*  loopback_self_test checks the integrity of the FPGA->AD936x->FPGA sample interface. +    The AD936x is put in loopback mode that sends the TX data unchanged to the RX side. +    A test value is written to the codec_idle register in the TX side of the radio. +    The readback register is then used to capture the values on the TX and RX sides +    simultaneously for comparison. It is a reasonably effective test for AC timing +    since I/Q Ch0/Ch1 alternate over the same wires. Note, however, that it uses +    whatever timing is configured at the time the test is called rather than select +    worst case conditions to stress the interface. +    Note: This currently only tests 2R2T mode +*/ +void e320_radio_ctrl_impl::loopback_self_test( +    std::function<void(uint32_t)> poker_functor, std::function<uint64_t()> peeker_functor) +{ +    // Save current rate before running this test +    const double current_rate = this->get_rate(); +    // Set 2R2T mode, stream on all channels +    this->set_streaming_mode(true, true, true, true); +    // Set maximum rate for 2R2T mode +    this->set_rate(30.72e6); +    // Put AD936x in loopback mode +    _ad9361->data_port_loopback(true); +    UHD_LOG_INFO(unique_id(), "Performing CODEC loopback test... "); +    size_t hash                     = size_t(time(NULL)); +    constexpr size_t loopback_count = 100; + +    // Allow some time for AD936x to enter loopback mode. +    // There is no clear statement in the documentation of how long it takes, +    // but UG-570 does say to "allow six ADC_CLK/64 clock cycles of flush time" +    // when leaving the TX or RX states.  That works out to ~75us at the +    // minimum clock rate of 5 MHz, which lines up with test results. +    // Sleeping 1ms is far more than enough. +    std::this_thread::sleep_for(std::chrono::milliseconds(1)); + +    for (size_t i = 0; i < loopback_count; i++) { +        // Create test word +        boost::hash_combine(hash, i); +        const uint32_t word32 = uint32_t(hash) & 0xfff0fff0; +        // const uint32_t word32 = 0xCA00C100; +        // Write test word to codec_idle idle register (on TX side) +        poker_functor(word32); + +        // Read back values - TX is lower 32-bits and RX is upper 32-bits +        const uint64_t rb_word64 = peeker_functor(); +        const uint32_t rb_tx     = uint32_t(rb_word64 >> 32); +        const uint32_t rb_rx     = uint32_t(rb_word64 & 0xffffffff); + +        // Compare TX and RX values to test word +        bool test_fail = word32 != rb_tx or word32 != rb_rx; +        if (test_fail) { +            UHD_LOG_WARNING(unique_id(), +                "CODEC loopback test failed! " +                    << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") +                           % word32 % rb_tx % rb_rx); +            throw uhd::runtime_error("CODEC loopback test failed."); +        } +    } +    UHD_LOG_INFO(unique_id(), "CODEC loopback test passed"); + +    // Zero out the idle data. +    poker_functor(0); + +    // Take AD936x out of loopback mode +    _ad9361->data_port_loopback(false); +    this->set_streaming_mode(true, false, true, false); +    // Switch back to current rate +    this->set_rate(current_rate); +} + +uint32_t e320_radio_ctrl_impl::get_tx_switches(const size_t chan, const double freq) +{ +    UHD_LOG_TRACE( +        unique_id(), "Update all TX freq related switches. f=" << freq << " Hz, "); +    auto tx_sw1 = TX_SW1_LB_160; +    auto tx_sw2 = TX_SW2_LB_160; +    auto trx_sw = (chan == 0) ? TRX1_SW_TX_LB : TRX2_SW_TX_LB; +    auto tx_amp = TX_AMP_LF_ON; + +    const auto band = e3xx_radio_ctrl_impl::map_freq_to_tx_band(freq); +    switch (band) { +        case tx_band::LB_80: +            tx_sw1 = TX_SW1_LB_80; +            tx_sw2 = TX_SW2_LB_80; +            break; +        case tx_band::LB_160: +            tx_sw1 = TX_SW1_LB_160; +            tx_sw2 = TX_SW2_LB_160; +            break; +        case tx_band::LB_225: +            tx_sw1 = TX_SW1_LB_225; +            tx_sw2 = TX_SW2_LB_225; +            break; +        case tx_band::LB_400: +            tx_sw1 = TX_SW1_LB_400; +            tx_sw2 = TX_SW2_LB_400; +            break; +        case tx_band::LB_575: +            tx_sw1 = TX_SW1_LB_575; +            tx_sw2 = TX_SW2_LB_575; +            break; +        case tx_band::LB_1000: +            tx_sw1 = TX_SW1_LB_1000; +            tx_sw2 = TX_SW2_LB_1000; +            break; +        case tx_band::LB_1700: +            tx_sw1 = TX_SW1_LB_1700; +            tx_sw2 = TX_SW2_LB_1700; +            break; +        case tx_band::LB_2750: +            tx_sw1 = TX_SW1_LB_2750; +            tx_sw2 = TX_SW2_LB_2750; +            break; +        case tx_band::HB: +            trx_sw = (chan == 0) ? TRX1_SW_TX_HB : TRX2_SW_TX_HB; +            tx_amp = TX_AMP_HF_ON; +            break; +        case tx_band::INVALID_BAND: +            UHD_LOG_ERROR(unique_id(), "Cannot map TX frequency to band: " << freq); +            UHD_THROW_INVALID_CODE_PATH(); +            break; +    } + +    auto tx_regs = tx_amp << TX_AMP_SHIFT | trx_sw << TRX_SW_SHIFT +                   | tx_sw2 << TX_SW2_SHIFT | tx_sw1 << TX_SW1_SHIFT; +    return tx_regs; +} + +uint32_t e320_radio_ctrl_impl::get_rx_switches( +    const size_t chan, const double freq, const std::string& ant) +{ +    UHD_LOG_TRACE( +        unique_id(), "Update all RX freq related switches. f=" << freq << " Hz, "); +    // Default to OFF +    auto rx_sw1 = RX_SW1_OFF; +    auto rx_sw2 = RX_SW2_OFF; +    auto rx_sw3 = RX_SW3_OFF; +    auto trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; +    if (ant == "TX/RX") { +        rx_sw3 = RX_SW3_HBRX_LBTRX; +        trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; +    } else if (ant == "RX2") { +        rx_sw3 = RX_SW3_HBTRX_LBRX; +        // Set TRX switch to TX when receiving on RX2 +        trx_sw = TRX1_SW_TX_HB; +    } + +    const auto band = e3xx_radio_ctrl_impl::map_freq_to_rx_band(freq); +    switch (band) { +        case rx_band::LB_B2: +            rx_sw1 = RX_SW1_LB_B2; +            rx_sw2 = RX_SW2_LB_B2; +            break; +        case rx_band::LB_B3: +            rx_sw1 = RX_SW1_LB_B3; +            rx_sw2 = RX_SW2_LB_B3; +            break; +        case rx_band::LB_B4: +            rx_sw1 = RX_SW1_LB_B4; +            rx_sw2 = RX_SW2_LB_B4; +            break; +        case rx_band::LB_B5: +            rx_sw1 = RX_SW1_LB_B5; +            rx_sw2 = RX_SW2_LB_B5; +            break; +        case rx_band::LB_B6: +            rx_sw1 = RX_SW1_LB_B6; +            rx_sw2 = RX_SW2_LB_B6; +            break; +        case rx_band::LB_B7: +            rx_sw1 = RX_SW1_LB_B7; +            rx_sw2 = RX_SW2_LB_B7; +            break; +        case rx_band::HB: +            rx_sw1 = RX_SW1_OFF; +            rx_sw2 = RX_SW2_OFF; +            if (ant == "TX/RX") { +                rx_sw3 = RX_SW3_HBTRX_LBRX; +            } else if (ant == "RX2") { +                rx_sw3 = RX_SW3_HBRX_LBTRX; +            } +            break; +        case rx_band::INVALID_BAND: +            UHD_LOG_ERROR(unique_id(), "Cannot map RX frequency to band: " << freq); +            UHD_THROW_INVALID_CODE_PATH(); +            break; +    } + +    auto rx_regs = trx_sw << TRX_SW_SHIFT | rx_sw3 << RX_SW3_SHIFT +                   | rx_sw2 << RX_SW2_SHIFT | rx_sw1 << RX_SW1_SHIFT; +    return rx_regs; +} + +uint32_t e320_radio_ctrl_impl::get_idle_switches() +{ +    uint32_t idle_regs = TX_AMP_OFF << TX_AMP_SHIFT | TRX1_SW_TX_HB << TRX_SW_SHIFT +                         | TX_SW2_LB_80 << TX_SW2_SHIFT | TX_SW1_LB_80 << TX_SW1_SHIFT +                         | RX_SW3_OFF << RX_SW3_SHIFT | RX_SW2_OFF << RX_SW2_SHIFT +                         | RX_SW1_OFF << RX_SW1_SHIFT; +    return idle_regs; +} + +uint32_t e320_radio_ctrl_impl::get_idle_led() +{ +    return 0; +} + +uint32_t e320_radio_ctrl_impl::get_rx_led() +{ +    return 1 << TRX_LED_GRN_SHIFT; +} + +uint32_t e320_radio_ctrl_impl::get_tx_led() +{ +    return 1 << TX_LED_RED_SHIFT; +} + +uint32_t e320_radio_ctrl_impl::get_txrx_led() +{ +    return 1 << RX_LED_GRN_SHIFT; +} +UHD_RFNOC_BLOCK_REGISTER(e320_radio_ctrl, "NeonRadio"); diff --git a/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.hpp new file mode 100644 index 000000000..7f75cadc7 --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e320_radio_ctrl_impl.hpp @@ -0,0 +1,134 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_E320_RADIO_CTRL_IMPL_HPP +#    define INCLUDED_LIBUHD_RFNOC_E320_RADIO_CTRL_IMPL_HPP + +#    include "e3xx_constants.hpp" +#    include "e3xx_radio_ctrl_impl.hpp" + +namespace uhd { namespace rfnoc { + +/*! \brief Provide access to an E320 radio. + */ +class e320_radio_ctrl_impl : public e3xx_radio_ctrl_impl +{ +public: +    /************************************************************************ +     * Structors +     ***********************************************************************/ +    e320_radio_ctrl_impl(const make_args_t& make_args); +    virtual ~e320_radio_ctrl_impl(); + +protected: +    /************************************************************************** +     * ATR/ Switches Types +     *************************************************************************/ + +    enum tx_sw1_t { +        TX_SW1_LB_80   = 3, +        TX_SW1_LB_160  = 7, +        TX_SW1_LB_225  = 1, +        TX_SW1_LB_400  = 5, +        TX_SW1_LB_575  = 2, +        TX_SW1_LB_1000 = 6, +        TX_SW1_LB_1700 = 0, +        TX_SW1_LB_2750 = 4 +    }; + +    enum tx_sw2_t { +        TX_SW2_LB_80   = 7, +        TX_SW2_LB_160  = 3, +        TX_SW2_LB_225  = 5, +        TX_SW2_LB_400  = 1, +        TX_SW2_LB_575  = 6, +        TX_SW2_LB_1000 = 2, +        TX_SW2_LB_1700 = 4, +        TX_SW2_LB_2750 = 0 +    }; + +    enum trx_sw_t { +        TRX1_SW_TX_HB = 2, +        TRX1_SW_TX_LB = 1, +        TRX1_SW_RX    = 4, +        TRX2_SW_TX_HB = 2, +        TRX2_SW_TX_LB = 4, +        TRX2_SW_RX    = 1 +    }; + +    enum rx_sw1_t { +        RX_SW1_LB_B2 = 4, +        RX_SW1_LB_B3 = 5, +        RX_SW1_LB_B4 = 2, +        RX_SW1_LB_B5 = 3, +        RX_SW1_LB_B6 = 0, +        RX_SW1_LB_B7 = 1, +        RX_SW1_OFF   = 7 + +    }; + +    enum rx_sw2_t { +        RX_SW2_LB_B2 = 5, +        RX_SW2_LB_B3 = 4, +        RX_SW2_LB_B4 = 3, +        RX_SW2_LB_B5 = 2, +        RX_SW2_LB_B6 = 1, +        RX_SW2_LB_B7 = 0, +        RX_SW2_OFF   = 7 +    }; + +    enum rx_sw3_t { +        RX_SW3_HBRX_LBTRX = 1, +        RX_SW3_HBTRX_LBRX = 2, +        RX_SW3_OFF        = 0 // or 3 +    }; + +    enum tx_amp_t { TX_AMP_HF_ON = 2, TX_AMP_LF_ON = 1, TX_AMP_OFF = 3 }; + +    /************************************************************************ +     * API calls +     ***********************************************************************/ +    virtual bool check_radio_config(); + +    const std::string get_default_timing_mode() +    { +        return TIMING_MODE_2R2T; +    }; + +    /*! Run a loopback self test. +     * +     * This will write data to the AD936x and read it back again. +     * If this test fails, it generally means the interface is broken, +     * so we assume it passes and throw otherwise. Running this requires +     * a core that we can peek and poke the loopback values into. +     * +     * \param iface An interface to the associated radio control core +     * \param iface The radio control core's address to write the loopback value +     * \param iface The radio control core's readback address to read back the returned +     * value +     * +     * \throws a uhd::runtime_error if the loopback value didn't match. +     */ +    void loopback_self_test(std::function<void(uint32_t)> poker_functor, +        std::function<uint64_t()> peeker_functor); + +    uint32_t get_rx_switches( +        const size_t chan, const double freq, const std::string& ant); + +    uint32_t get_tx_switches(const size_t chan, const double freq); + +    uint32_t get_idle_switches(); + +    uint32_t get_tx_led(); +    uint32_t get_rx_led(); +    uint32_t get_txrx_led(); +    uint32_t get_idle_led(); +}; /* class radio_ctrl_impl */ + +}} /* namespace uhd::rfnoc */ + +#endif /* INCLUDED_LIBUHD_RFNOC_E320_RADIO_CTRL_IMPL_HPP */ +// vim: sw=4 et: diff --git a/host/lib/usrp/dboard/neon/neon_regs.hpp b/host/lib/usrp/dboard/e3xx/e320_regs.hpp index d1ff940c6..f5d28a63e 100644 --- a/host/lib/usrp/dboard/neon/neon_regs.hpp +++ b/host/lib/usrp/dboard/e3xx/e320_regs.hpp @@ -4,8 +4,8 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#ifndef INCLUDED_NEON_REGS_HPP -#define INCLUDED_NEON_REGS_HPP +#ifndef INCLUDED_E320_REGS_HPP +#define INCLUDED_E320_REGS_HPP  #include <uhd/config.hpp>  #include <cstdint> @@ -22,4 +22,4 @@ static const uint32_t TRX_LED_GRN_SHIFT = 0;  static const uint32_t TX_LED_RED_SHIFT  = 1;  static const uint32_t RX_LED_GRN_SHIFT  = 2; -#endif /* INCLUDED_NEON_REGS_HPP */ +#endif /* INCLUDED_E320_REGS_HPP */ diff --git a/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp b/host/lib/usrp/dboard/e3xx/e3xx_ad9361_iface.cpp index a9cf28fc2..d9cadc86f 100644 --- a/host/lib/usrp/dboard/neon/neon_ad9361_iface.cpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_ad9361_iface.cpp @@ -4,17 +4,17 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#include "neon_ad9361_iface.hpp" +#include "e3xx_ad9361_iface.hpp"  #include <uhd/exception.hpp>  #include <uhd/utils/log.hpp>  #include <boost/format.hpp>  using namespace uhd; -class neon_ad9361_iface : public ad9361_ctrl +class e3xx_ad9361_iface : public ad9361_ctrl  {  public: -    neon_ad9361_iface(rpc_client::sptr rpcc) +    e3xx_ad9361_iface(rpc_client::sptr rpcc)          : _rpcc(rpcc), _rpc_prefix("db_0_"), _log_prefix("AD9361")      {          UHD_LOG_TRACE( @@ -46,7 +46,7 @@ public:      double set_clock_rate(const double rate)      {          return _rpcc->request_with_token<double>( -            this->_rpc_prefix + "set_clock_rate", rate); +            E3XX_RATE_TIMEOUT, this->_rpc_prefix + "set_catalina_clock_rate", rate);      }      void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) @@ -58,7 +58,7 @@ public:      double tune(const std::string& which, const double value)      {          return _rpcc->request_with_token<double>( -            this->_rpc_prefix + "tune", which, value); +            E3XX_TUNE_TIMEOUT, this->_rpc_prefix + "catalina_tune", which, value);      }      void set_dc_offset_auto(const std::string& which, const bool on) @@ -139,17 +139,18 @@ private:      const std::string _log_prefix;  }; -//! Factory function for Neon's AD9361 RPC Controller +//! Factory function for E3xx's AD9361 RPC Controller  ad9361_ctrl::sptr make_rpc(rpc_client::sptr rpcc)  { -    return ad9361_ctrl::sptr(new neon_ad9361_iface(rpcc)); +    return ad9361_ctrl::sptr(new e3xx_ad9361_iface(rpcc));  }  /*! Helper function to convert direction and channel to the 'which' required by most     Catalina driver functions */ -std::string get_which_ad9361_chain(const direction_t dir, const size_t chan) +std::string get_which_ad9361_chain(const direction_t dir, const size_t chan, const bool fe_swap)  {      UHD_ASSERT_THROW(dir == RX_DIRECTION or dir == TX_DIRECTION);      UHD_ASSERT_THROW(chan == 0 or chan == 1); -    return str(boost::format("%s%d") % (dir == RX_DIRECTION ? "RX" : "TX") % (chan + 1)); +    size_t ad9361_chan = fe_swap ? (chan ? 0 : 1) : chan; +    return str(boost::format("%s%d") % (dir == RX_DIRECTION ? "RX" : "TX") % (ad9361_chan + 1));  } diff --git a/host/lib/usrp/dboard/e3xx/e3xx_ad9361_iface.hpp b/host/lib/usrp/dboard/e3xx/e3xx_ad9361_iface.hpp new file mode 100644 index 000000000..129015420 --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e3xx_ad9361_iface.hpp @@ -0,0 +1,28 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_E3XX_AD9361_IFACE_HPP +#define INCLUDED_LIBUHD_RFNOC_E3XX_AD9361_IFACE_HPP + +#    include <uhd/types/direction.hpp> +#    include <uhd/types/filters.hpp> +#    include <uhd/types/sensors.hpp> +#    include <uhdlib/usrp/common/ad9361_ctrl.hpp> +#    include <uhdlib/utils/rpc.hpp> +#    include <memory> +#    include <string> +#    include <vector> + +using namespace uhd; +using namespace uhd::usrp; + +static constexpr size_t E3XX_TUNE_TIMEOUT = 60000; +static constexpr size_t E3XX_RATE_TIMEOUT = 60000; +ad9361_ctrl::sptr make_rpc(rpc_client::sptr rpcc); +std::string get_which_ad9361_chain(const direction_t dir, const size_t chan, const bool fe_swap=false); + +#endif /* INCLUDED_LIBUHD_RFNOC_E3XX_AD9361_IFACE_HPP */ +// vim: sw=4 et: diff --git a/host/lib/usrp/dboard/neon/neon_bands.cpp b/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp index 303d2801d..001cf5d1b 100644 --- a/host/lib/usrp/dboard/neon/neon_bands.cpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_bands.cpp @@ -4,12 +4,12 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#include "neon_constants.hpp" -#include "neon_radio_ctrl_impl.hpp" +#include "e3xx_constants.hpp" +#include "e3xx_radio_ctrl_impl.hpp"  #include <uhd/utils/math.hpp>  /* - * Neon frequency bands: + * E320 frequency bands:   *   * For RX:   *     Band   Freq      BSEL-210 BSEL-543         TX/RX                RX2 @@ -41,7 +41,41 @@   *     LB_1000 723.8-1154.9   RF4 110  RF3 010   RF1 001   RF3 100   *     LB_1700 1154.9-1842.6  RF1 000  RF2 100   RF1 001   RF3 100   *     LB_2750 1842.6-2940.0  RF2 100  RF1 000   RF1 001   RF3 100 - *     HB_5850 > 2490.0       --- ---  --- ---   RF2 010   RF2 010 + *     HB_5850 > 2940.0       --- ---  --- ---   RF2 010   RF2 010 + * + */ + +/* + * E31x frequency bands: + * + * For RX: + *     Band   Freq      RX_BSEL-210 RXC_BSEL-10 RXB_BSEL-10   RX2            TX/RX + *                                                          VCRX_V1_V2    VCTXRX_V1_V2 + *                                                                       chan 1 | chan 2 + *     --------------------------------------------------------------------------------- + *     LB_B2: < 450       RF5 100    J2 10       -- 00          01       J2 10    J1 01 + *     LB_B3: 450-700     RF3 010    J3 11       -- 00          01       J2 10    J1 01 + *     LB_B4: 700-1200    RF1 000    J1 01       -- 00          01       J2 10    J1 01 + *     LB_B5: 1200-1800   RF2 001    -- 00       J2 10          01       J2 10    J1 01 + *     LB_B6: 1800-2350   RF4 011    -- 00       J3 11          01       J2 10    J1 01 + *     LB_B7: 2350-2600   RF6 101    -- 00       J1 01          01       J2 10    J1 01 + *     HB:    2600+       --- 111    -- 00       -- 00          10       J2 10    J1 01 + * + * + * For TX: + *     Band-Freq              TX_BSEL-210           TX/RX +                                                VCTXRX_V1_V2 + *                                             chan 1 | chan 2 + *     ------------------------------------------------------------ + *     LB_80   < 117.7        RF8 111          J1 01    J2 10 + *     LB_160  117.7-178.2    RF7 110          J1 01    J2 10 + *     LB_225  178.2-284.3    RF6 101          J1 01    J2 10 + *     LB_400  284.3-453.7    RF5 100          J1 01    J2 10 + *     LB_575  453.7-723.8    RF4 011          J1 01    J2 10 + *     LB_1000 723.8-1154.9   RF3 010          J1 01    J2 10 + *     LB_1700 1154.9-1842.6  RF2 001          J1 01    J2 10 + *     LB_2750 1842.6-2940.0  RF1 000          J1 01    J2 10 + *     HB_5850 > 2940.0       RF8 111          J3 11    J3 11   *   */ @@ -58,19 +92,19 @@ namespace {   *   * The following constants define lower cutoff frequencies for each band.   * LB_B2 does not have a lower cutoff frequency, it is implied by - * AD9361_MIN_FREQ. NEON_RX_BAND1_MIN_FREQ is the cutover frequency + * AD9361_MIN_FREQ. E3XX_RX_BAND1_MIN_FREQ is the cutover frequency   * for switching from LB_B2 to LB_B3, and so on.   *   * Bands 1-6 have both high- and low-pass filters (effectively band   * passes). Frequencies need to be chosen to allow as much of the full   * bandwidth through unattenuated.   */ -constexpr double NEON_RX_LB_BAND3_MIN_FREQ = 450e6; -constexpr double NEON_RX_LB_BAND4_MIN_FREQ = 700e6; -constexpr double NEON_RX_LB_BAND5_MIN_FREQ = 1200e6; -constexpr double NEON_RX_LB_BAND6_MIN_FREQ = 1800e6; -constexpr double NEON_RX_LB_BAND7_MIN_FREQ = 2350e6; -constexpr double NEON_RX_HB_MIN_FREQ       = 2600e6; +constexpr double E3XX_RX_LB_BAND3_MIN_FREQ = 450e6; +constexpr double E3XX_RX_LB_BAND4_MIN_FREQ = 700e6; +constexpr double E3XX_RX_LB_BAND5_MIN_FREQ = 1200e6; +constexpr double E3XX_RX_LB_BAND6_MIN_FREQ = 1800e6; +constexpr double E3XX_RX_LB_BAND7_MIN_FREQ = 2350e6; +constexpr double E3XX_RX_HB_MIN_FREQ       = 2600e6;  /* Note on the TX filter bank:   * @@ -78,43 +112,42 @@ constexpr double NEON_RX_HB_MIN_FREQ       = 2600e6;   *   * The following constants define lower cutoff frequencies for each band.   * LB_80 does not have a lower cutoff frequency, it is implied by - * AD9361_MIN_FREQ. NEON_TX_LB_160_MIN_FREQ is the cutover frequency + * AD9361_MIN_FREQ. E3XX_TX_LB_160_MIN_FREQ is the cutover frequency   * for switching from LB_80 to LB_160, and so on.   * - * On current Neon revisions, all filters on the TX filter bank are + * All filters on the TX filter bank are   * low pass filters (no high pass filters).   * Frequencies need to be chosen to allow as much of the full bandwidth   * through unattenuated (so don't go all the way up to the cutoff frequency   * of that filter).   */ -constexpr double NEON_TX_LB_160_MIN_FREQ  = 117.7e6; -constexpr double NEON_TX_LB_225_MIN_FREQ  = 178.2e6; -constexpr double NEON_TX_LB_400_MIN_FREQ  = 284.3e6; -constexpr double NEON_TX_LB_575_MIN_FREQ  = 453.7e6; -constexpr double NEON_TX_LB_1000_MIN_FREQ = 723.8e6; -constexpr double NEON_TX_LB_1700_MIN_FREQ = 1154.9e6; -constexpr double NEON_TX_LB_2750_MIN_FREQ = 1842.6e6; -constexpr double NEON_TX_HB_MIN_FREQ      = 2940.0e6; +constexpr double E3XX_TX_LB_160_MIN_FREQ  = 117.7e6; +constexpr double E3XX_TX_LB_225_MIN_FREQ  = 178.2e6; +constexpr double E3XX_TX_LB_400_MIN_FREQ  = 284.3e6; +constexpr double E3XX_TX_LB_575_MIN_FREQ  = 453.7e6; +constexpr double E3XX_TX_LB_1000_MIN_FREQ = 723.8e6; +constexpr double E3XX_TX_LB_1700_MIN_FREQ = 1154.9e6; +constexpr double E3XX_TX_LB_2750_MIN_FREQ = 1842.6e6; +constexpr double E3XX_TX_HB_MIN_FREQ      = 2940.0e6;  } // namespace -neon_radio_ctrl_impl::rx_band neon_radio_ctrl_impl::_map_freq_to_rx_band( -    const double freq) +e3xx_radio_ctrl_impl::rx_band e3xx_radio_ctrl_impl::map_freq_to_rx_band(const double freq)  { -    neon_radio_ctrl_impl::rx_band band; +    e3xx_radio_ctrl_impl::rx_band band;      if (fp_compare_epsilon<double>(freq) < AD9361_RX_MIN_FREQ) {          band = rx_band::INVALID_BAND; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND3_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND3_MIN_FREQ) {          band = rx_band::LB_B2; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND4_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND4_MIN_FREQ) {          band = rx_band::LB_B3; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND5_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND5_MIN_FREQ) {          band = rx_band::LB_B4; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND6_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND6_MIN_FREQ) {          band = rx_band::LB_B5; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND7_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_LB_BAND7_MIN_FREQ) {          band = rx_band::LB_B6; -    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_HB_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_RX_HB_MIN_FREQ) {          band = rx_band::LB_B7;      } else if (fp_compare_epsilon<double>(freq) <= AD9361_RX_MAX_FREQ) {          band = rx_band::HB; @@ -125,28 +158,27 @@ neon_radio_ctrl_impl::rx_band neon_radio_ctrl_impl::_map_freq_to_rx_band(      return band;  } -neon_radio_ctrl_impl::tx_band neon_radio_ctrl_impl::_map_freq_to_tx_band( -    const double freq) +e3xx_radio_ctrl_impl::tx_band e3xx_radio_ctrl_impl::map_freq_to_tx_band(const double freq)  { -    neon_radio_ctrl_impl::tx_band band; +    e3xx_radio_ctrl_impl::tx_band band;      if (fp_compare_epsilon<double>(freq) < AD9361_TX_MIN_FREQ) {          band = tx_band::INVALID_BAND; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_160_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_160_MIN_FREQ) {          band = tx_band::LB_80; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_225_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_225_MIN_FREQ) {          band = tx_band::LB_160; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_400_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_400_MIN_FREQ) {          band = tx_band::LB_225; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_575_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_575_MIN_FREQ) {          band = tx_band::LB_400; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_1000_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_1000_MIN_FREQ) {          band = tx_band::LB_575; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_1700_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_1700_MIN_FREQ) {          band = tx_band::LB_1000; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_2750_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_LB_2750_MIN_FREQ) {          band = tx_band::LB_1700; -    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_HB_MIN_FREQ) { +    } else if (fp_compare_epsilon<double>(freq) < E3XX_TX_HB_MIN_FREQ) {          band = tx_band::LB_2750;      } else if (fp_compare_epsilon<double>(freq) <= AD9361_TX_MAX_FREQ) {          band = tx_band::HB; diff --git a/host/lib/usrp/dboard/neon/neon_constants.hpp b/host/lib/usrp/dboard/e3xx/e3xx_constants.hpp index 42cfb6579..53f64d837 100644 --- a/host/lib/usrp/dboard/neon/neon_constants.hpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_constants.hpp @@ -4,8 +4,8 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#ifndef INCLUDED_LIBUHD_NEON_CONSTANTS_HPP -#define INCLUDED_LIBUHD_NEON_CONSTANTS_HPP +#ifndef INCLUDED_LIBUHD_E3XX_CONSTANTS_HPP +#define INCLUDED_LIBUHD_E3XX_CONSTANTS_HPP  #include <cstddef>  #include <string> @@ -25,7 +25,7 @@ static constexpr double AD9361_TX_MAX_FREQ = 6.0e9; // Hz  static constexpr double AD9361_RX_MIN_FREQ = 70.0e6; // Hz  static constexpr double AD9361_RX_MAX_FREQ = 6.0e9; // Hz -static constexpr double NEON_RADIO_RATE = 16e6; // Hz +static constexpr double E3XX_RADIO_RATE = 16e6; // Hz  static constexpr double AD9361_MIN_RX_GAIN  = 0.0; // dB  static constexpr double AD9361_MAX_RX_GAIN  = 76; // dB @@ -34,19 +34,23 @@ static constexpr double AD9361_MIN_TX_GAIN  = 0.0; // dB  static constexpr double AD9361_MAX_TX_GAIN  = 89.75; // dB  static constexpr double AD9361_TX_GAIN_STEP = 0.25; // dB +static constexpr bool E3XX_DEFAULT_AUTO_DC_OFFSET  = true; +static constexpr bool E3XX_DEFAULT_AUTO_IQ_BALANCE = true; +static constexpr bool E3XX_DEFAULT_AGC_ENABLE      = false; -static constexpr bool NEON_DEFAULT_AUTO_DC_OFFSET  = true; -static constexpr bool NEON_DEFAULT_AUTO_IQ_BALANCE = true; -static constexpr bool NEON_DEFAULT_AGC_ENABLE      = false; +static constexpr double E3XX_DEFAULT_GAIN       = 0.0; +static constexpr double E3XX_DEFAULT_FREQ       = 2.4e9; // Hz +static constexpr double E3XX_DEFAULT_BANDWIDTH  = 40e6; // Hz +static constexpr char E3XX_DEFAULT_RX_ANTENNA[] = "RX2"; +static constexpr char E3XX_DEFAULT_TX_ANTENNA[] = "TX/RX"; -static constexpr double NEON_DEFAULT_GAIN       = 0.0; -static constexpr double NEON_DEFAULT_FREQ       = 2.4e9; // Hz -static constexpr double NEON_DEFAULT_BANDWIDTH  = 40e6; // Hz -static constexpr char NEON_DEFAULT_RX_ANTENNA[] = "RX2"; -static constexpr char NEON_DEFAULT_TX_ANTENNA[] = "TX/RX"; +static const std::vector<std::string> E3XX_RX_ANTENNAS = {"RX2", "TX/RX"}; -static const std::vector<std::string> NEON_RX_ANTENNAS = {"RX2", "TX/RX"}; +static constexpr size_t E3XX_NUM_CHANS = 2; -static constexpr size_t NEON_NUM_CHANS = 2; - -#endif /* INCLUDED_LIBUHD_NEON_CONSTANTS_HPP */ +static constexpr char TIMING_MODE_2R2T[] = "2R2T"; +static constexpr char TIMING_MODE_1R1T[] = "1R1T"; +static constexpr char MIMO[]             = "MIMO"; // 2R2T +static constexpr char SISO_TX1[]         = "SISO_TX1"; // 1R1T +static constexpr char SISO_TX0[]         = "SISO_TX0"; // 1R1T +#endif /* INCLUDED_LIBUHD_E3XX_CONSTANTS_HPP */ diff --git a/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_impl.cpp new file mode 100644 index 000000000..989b73b82 --- /dev/null +++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_impl.cpp @@ -0,0 +1,343 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#include "e3xx_radio_ctrl_impl.hpp" +#include "e3xx_constants.hpp" +#include <uhd/rfnoc/node_ctrl_base.hpp> +#include <uhd/transport/chdr.hpp> +#include <uhd/types/direction.hpp> +#include <uhd/types/eeprom.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/math.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/format.hpp> +#include <boost/make_shared.hpp> +#include <cmath> +#include <cstdlib> +#include <sstream> + +using namespace uhd; +using namespace uhd::usrp; +using namespace uhd::rfnoc; +using namespace uhd::math::fp_compare; + +/****************************************************************************** + * Structors + *****************************************************************************/ +e3xx_radio_ctrl_impl::e3xx_radio_ctrl_impl() +{ +    UHD_LOG_TRACE(unique_id(), "Entering e3xx_radio_ctrl_impl ctor..."); +    const char radio_slot_name[1] = {'A'}; +    _radio_slot                   = radio_slot_name[get_block_id().get_block_count()]; +    UHD_LOG_TRACE(unique_id(), "Radio slot: " << _radio_slot); +    _rpc_prefix = "db_0_"; + +    _init_defaults(); +    _init_peripherals(); +    _init_prop_tree(); +} + +e3xx_radio_ctrl_impl::~e3xx_radio_ctrl_impl() +{ +    UHD_LOG_TRACE(unique_id(), "e3xx_radio_ctrl_impl::dtor() "); +} + + +/****************************************************************************** + * API Calls + *****************************************************************************/ + +void e3xx_radio_ctrl_impl::set_streaming_mode( +    const bool tx1, const bool tx2, const bool rx1, const bool rx2) +{ +    UHD_LOG_TRACE(unique_id(), "Setting up streaming ...") +    const size_t num_rx = rx1 + rx2; +    const size_t num_tx = tx1 + tx2; + +    // setup the active chains in the codec +    if ((num_rx + num_tx) == 0) { +        // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock +        _ad9361->set_active_chains(true, false, true, false); +    } else { +        // setup the active chains in the codec +        _ad9361->set_active_chains(tx1, tx2, rx1, rx2); +    } + +    // setup 1R1T/2R2T mode in catalina and fpga +    // The Catalina interface in the fpga needs to know which TX channel to use for +    // the data on the LVDS lines. +    if ((num_rx == 2) or (num_tx == 2)) { +        // AD9361 is in 1R1T mode +        _ad9361->set_timing_mode(this->get_default_timing_mode()); +        this->set_channel_mode(MIMO); +    } else { +        // AD9361 is in 1R1T mode +        _ad9361->set_timing_mode(TIMING_MODE_1R1T); + +        // Set to SIS0_TX1 if we're using the second TX antenna, otherwise +        // default to SISO_TX0 +        this->set_channel_mode(tx2 ? SISO_TX1 : SISO_TX0); +    } +} + +void e3xx_radio_ctrl_impl::set_channel_mode(const std::string& channel_mode) +{ +    // MIMO for 2R2T mode for 2 channels +    // SISO_TX1 for 1R1T mode for 1 channel - TX1 +    // SISO_TX0 for 1R1T mode for 1 channel - TX0 + +    _rpcc->request_with_token<void>("set_channel_mode", channel_mode); +} + +double e3xx_radio_ctrl_impl::set_rate(const double rate) +{ +    std::lock_guard<std::mutex> l(_set_lock); +    UHD_LOG_DEBUG(unique_id(), "Asking for clock rate " << rate / 1e6 << " MHz\n"); +    double actual_tick_rate = _ad9361->set_clock_rate(rate); +    UHD_LOG_DEBUG( +        unique_id(), "Actual clock rate " << actual_tick_rate / 1e6 << " MHz\n"); + +    radio_ctrl_impl::set_rate(rate); +    return rate; +} + +void e3xx_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) +{ +    if (ant != get_tx_antenna(chan)) { +        throw uhd::value_error( +            str(boost::format("[%s] Requesting invalid TX antenna value: %s") +                % unique_id() % ant)); +    } +    radio_ctrl_impl::set_tx_antenna(ant, chan); +    // We can't actually set the TX antenna, so let's stop here. +} + +void e3xx_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) +{ +    UHD_ASSERT_THROW(chan <= E3XX_NUM_CHANS); +    if (std::find(E3XX_RX_ANTENNAS.begin(), E3XX_RX_ANTENNAS.end(), ant) +        == E3XX_RX_ANTENNAS.end()) { +        throw uhd::value_error( +            str(boost::format("[%s] Requesting invalid RX antenna value: %s") +                % unique_id() % ant)); +    } +    UHD_LOG_TRACE(unique_id(), "Setting RX antenna to " << ant << " for chan " << chan); + +    radio_ctrl_impl::set_rx_antenna(ant, chan); +    _set_atr_bits(chan); +} + +double e3xx_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) +{ +    UHD_LOG_TRACE(unique_id(), "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); +    std::lock_guard<std::mutex> l(_set_lock); + +    double clipped_freq = uhd::clip(freq, AD9361_TX_MIN_FREQ, AD9361_TX_MAX_FREQ); + +    double coerced_freq = +        _ad9361->tune(get_which_ad9361_chain(TX_DIRECTION, chan, _fe_swap), clipped_freq); +    radio_ctrl_impl::set_tx_frequency(coerced_freq, chan); +    // Front-end switching +    _set_atr_bits(chan); + +    return coerced_freq; +} + +double e3xx_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) +{ +    UHD_LOG_TRACE(unique_id(), "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); +    std::lock_guard<std::mutex> l(_set_lock); + +    double clipped_freq = uhd::clip(freq, AD9361_RX_MIN_FREQ, AD9361_RX_MAX_FREQ); + +    double coerced_freq = +        _ad9361->tune(get_which_ad9361_chain(RX_DIRECTION, chan, _fe_swap), clipped_freq); +    radio_ctrl_impl::set_rx_frequency(coerced_freq, chan); +    // Front-end switching +    _set_atr_bits(chan); + +    return coerced_freq; +} + +double e3xx_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) +{ +    std::lock_guard<std::mutex> l(_set_lock); +    double clipped_bw = +        _ad9361->set_bw_filter(get_which_ad9361_chain(RX_DIRECTION, chan, _fe_swap), bandwidth); +    return radio_ctrl_impl::set_rx_bandwidth(clipped_bw, chan); +} + +double e3xx_radio_ctrl_impl::set_tx_bandwidth(const double bandwidth, const size_t chan) +{ +    std::lock_guard<std::mutex> l(_set_lock); +    double clipped_bw = +        _ad9361->set_bw_filter(get_which_ad9361_chain(TX_DIRECTION, chan, _fe_swap), bandwidth); +    return radio_ctrl_impl::set_tx_bandwidth(clipped_bw, chan); +} + +double e3xx_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) +{ +    std::lock_guard<std::mutex> l(_set_lock); +    UHD_LOG_TRACE(unique_id(), "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); +    double clip_gain = uhd::clip(gain, AD9361_MIN_TX_GAIN, AD9361_MAX_TX_GAIN); +    _ad9361->set_gain(get_which_ad9361_chain(TX_DIRECTION, chan, _fe_swap), clip_gain); +    radio_ctrl_impl::set_tx_gain(clip_gain, chan); +    return clip_gain; +} + +double e3xx_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) +{ +    std::lock_guard<std::mutex> l(_set_lock); +    UHD_LOG_TRACE(unique_id(), "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); +    double clip_gain = uhd::clip(gain, AD9361_MIN_RX_GAIN, AD9361_MAX_RX_GAIN); +    _ad9361->set_gain(get_which_ad9361_chain(RX_DIRECTION, chan, _fe_swap), clip_gain); +    radio_ctrl_impl::set_rx_gain(clip_gain, chan); +    return clip_gain; +} + +size_t e3xx_radio_ctrl_impl::get_chan_from_dboard_fe( +    const std::string& fe, const direction_t /* dir */ +) +{ +    const size_t chan = boost::lexical_cast<size_t>(fe); +    if (chan > _get_num_radios() - 1) { +        UHD_LOG_WARNING(unique_id(), +            boost::format("Invalid channel determined from dboard frontend %s.") % fe); +    } +    return chan; +} + +std::string e3xx_radio_ctrl_impl::get_dboard_fe_from_chan( +    const size_t chan, const direction_t /* dir */ +) +{ +    return std::to_string(chan); +} + +void e3xx_radio_ctrl_impl::set_rpc_client( +    uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args) +{ +    _rpcc       = rpcc; +    _block_args = block_args; +    UHD_LOG_TRACE(unique_id(), "Instantiating AD9361 control object..."); +    _ad9361 = make_rpc(_rpcc); + +    UHD_LOG_TRACE(unique_id(), "Setting Catalina Defaults... "); +    // Initialize catalina +    this->_init_codec(); + +    if (block_args.has_key("identify")) { +        const std::string identify_val = block_args.get("identify"); +        int identify_duration          = std::atoi(identify_val.c_str()); +        if (identify_duration == 0) { +            identify_duration = 5; +        } +        UHD_LOG_INFO(unique_id(), +            "Running LED identification process for " << identify_duration +                                                      << " seconds."); +        _identify_with_leds(identify_duration); +    } +    // Note: MCR gets set during the init() call (prior to this), which takes +    // in arguments from the device args. So if block_args contains a +    // master_clock_rate key, then it should better be whatever the device is +    // configured to do. +    _master_clock_rate = +        _rpcc->request_with_token<double>(_rpc_prefix + "get_master_clock_rate"); +    if (block_args.cast<double>("master_clock_rate", _master_clock_rate) +        != _master_clock_rate) { +        throw uhd::runtime_error(str( +            boost::format("Master clock rate mismatch. Device returns %f MHz, " +                          "but should have been %f MHz.") +            % (_master_clock_rate / 1e6) +            % (block_args.cast<double>("master_clock_rate", _master_clock_rate) / 1e6))); +    } +    UHD_LOG_DEBUG( +        unique_id(), "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); +    this->set_rate(_master_clock_rate); + +    // Loopback test +    for (size_t chan = 0; chan < _get_num_radios(); chan++) { +        loopback_self_test( +            [this, chan]( +                const uint32_t value) { this->sr_write(regs::CODEC_IDLE, value, chan); }, +            [this, chan]() { +                return this->user_reg_read64(regs::RB_CODEC_READBACK, chan); +            }); +    } + +    const size_t db_idx = get_block_id().get_block_count(); +    _tree->access<eeprom_map_t>(_root_path / "eeprom") +        .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom) { +            this->_rpcc->notify_with_token("set_db_eeprom", db_idx, db_eeprom); +        }) +        .set_publisher([this, db_idx]() { +            return this->_rpcc->request_with_token<eeprom_map_t>("get_db_eeprom", db_idx); +        }); + +    // Init sensors +    for (const auto& dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { +        for (size_t chan_idx = 0; chan_idx < E3XX_NUM_CHANS; chan_idx++) { +            _init_mpm_sensors(dir, chan_idx); +        } +    } +} + +bool e3xx_radio_ctrl_impl::get_lo_lock_status(const direction_t dir) +{ +    if (not(bool(_rpcc))) { +        UHD_LOG_DEBUG(unique_id(), "Reported no LO lock due to lack of RPC connection."); +        return false; +    } + +    const std::string trx = (dir == RX_DIRECTION) ? "rx" : "tx"; +    bool lo_lock = +        _rpcc->request_with_token<bool>(_rpc_prefix + "get_ad9361_lo_lock", trx); +    UHD_LOG_TRACE(unique_id(), +        "AD9361 " << trx << " LO reports lock: " << (lo_lock ? "Yes" : "No")); + +    return lo_lock; +} + +void e3xx_radio_ctrl_impl::_set_atr_bits(const size_t chan) +{ +    const auto rx_freq       = radio_ctrl_impl::get_rx_frequency(chan); +    const auto tx_freq       = radio_ctrl_impl::get_tx_frequency(chan); +    const auto rx_ant        = radio_ctrl_impl::get_rx_antenna(chan); +    const uint32_t rx_regs   = this->get_rx_switches(chan, rx_freq, rx_ant); +    const uint32_t tx_regs   = this->get_tx_switches(chan, tx_freq); +    const uint32_t idle_regs = this->get_idle_switches(); + +    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_regs); +    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, rx_regs); +    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_regs); +    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, rx_regs | tx_regs); + +    // The LED signal names are reversed, but are consistent with the schematic +    const bool is_txrx = rx_ant == "TX/RX"; +    const int idle_led = 0; +    const int rx_led   = this->get_rx_led(); +    const int tx_led   = this->get_tx_led(); +    const int txrx_led = this->get_txrx_led(); + +    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_led); +    _leds_gpio[chan]->set_atr_reg( +        usrp::gpio_atr::ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led); +    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_led); +    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, rx_led | tx_led); +} + +void e3xx_radio_ctrl_impl::_identify_with_leds(const int identify_duration) +{ +    auto end_time = +        std::chrono::steady_clock::now() + std::chrono::seconds(identify_duration); +    bool led_state = true; +    while (std::chrono::steady_clock::now() < end_time) { +        // Add update_leds +        led_state = !led_state; +        std::this_thread::sleep_for(std::chrono::milliseconds(500)); +    } +} diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_impl.hpp index 88d1eed73..41c2c4594 100644 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.hpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_impl.hpp @@ -4,26 +4,26 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#ifndef INCLUDED_LIBUHD_RFNOC_NEON_RADIO_CTRL_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_NEON_RADIO_CTRL_IMPL_HPP - -#include "neon_ad9361_iface.hpp" -#include <uhd/types/serial.hpp> -#include <uhd/usrp/dboard_manager.hpp> -#include <uhd/usrp/gpio_defs.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhdlib/rfnoc/rpc_block_ctrl.hpp> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include <mutex> +#ifndef INCLUDED_LIBUHD_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP +#    define INCLUDED_LIBUHD_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP + +#    include "e3xx_ad9361_iface.hpp" +#    include <uhd/types/serial.hpp> +#    include <uhd/usrp/dboard_manager.hpp> +#    include <uhd/usrp/gpio_defs.hpp> +#    include <uhdlib/rfnoc/radio_ctrl_impl.hpp> +#    include <uhdlib/rfnoc/rpc_block_ctrl.hpp> +#    include <uhdlib/usrp/cores/gpio_atr_3000.hpp> +#    include <mutex>  namespace uhd { namespace rfnoc { -/*! \brief Provide access to an Magnesium radio. +/*! \brief Provide access to an E3xx radio.   */ -class neon_radio_ctrl_impl : public radio_ctrl_impl, public rpc_block_ctrl +class e3xx_radio_ctrl_impl : public radio_ctrl_impl, public rpc_block_ctrl  {  public: -    typedef boost::shared_ptr<neon_radio_ctrl_impl> sptr; +    typedef boost::shared_ptr<e3xx_radio_ctrl_impl> sptr;      //! Frequency bands for RX. Bands are a function of the analog filter banks      enum class rx_band { INVALID_BAND, LB_B2, LB_B3, LB_B4, LB_B5, LB_B6, LB_B7, HB }; @@ -51,86 +51,53 @@ public:      //! Channel select:      enum chan_sel_t { CHAN1, CHAN2, BOTH }; -    enum tx_sw1_t { -        TX_SW1_LB_80   = 3, -        TX_SW1_LB_160  = 7, -        TX_SW1_LB_225  = 1, -        TX_SW1_LB_400  = 5, -        TX_SW1_LB_575  = 2, -        TX_SW1_LB_1000 = 6, -        TX_SW1_LB_1700 = 0, -        TX_SW1_LB_2750 = 4 -    }; - -    enum tx_sw2_t { -        TX_SW2_LB_80   = 7, -        TX_SW2_LB_160  = 3, -        TX_SW2_LB_225  = 5, -        TX_SW2_LB_400  = 1, -        TX_SW2_LB_575  = 6, -        TX_SW2_LB_1000 = 2, -        TX_SW2_LB_1700 = 4, -        TX_SW2_LB_2750 = 0 -    }; - -    enum trx_sw_t { -        TRX1_SW_TX_HB = 2, -        TRX1_SW_TX_LB = 1, -        TRX1_SW_RX    = 4, -        TRX2_SW_TX_HB = 2, -        TRX2_SW_TX_LB = 4, -        TRX2_SW_RX    = 1 -    }; - -    enum rx_sw1_t { -        RX_SW1_LB_B2 = 4, -        RX_SW1_LB_B3 = 5, -        RX_SW1_LB_B4 = 2, -        RX_SW1_LB_B5 = 3, -        RX_SW1_LB_B6 = 0, -        RX_SW1_LB_B7 = 1, -        RX_SW1_OFF   = 7 - -    }; - -    enum rx_sw2_t { -        RX_SW2_LB_B2 = 5, -        RX_SW2_LB_B3 = 4, -        RX_SW2_LB_B4 = 3, -        RX_SW2_LB_B5 = 2, -        RX_SW2_LB_B6 = 1, -        RX_SW2_LB_B7 = 0, -        RX_SW2_OFF   = 7 -    }; - -    enum rx_sw3_t { -        RX_SW3_HBRX_LBTRX = 1, -        RX_SW3_HBTRX_LBRX = 2, -        RX_SW3_OFF        = 0 // or 3 -    }; - -    enum tx_amp_t { TX_AMP_HF_ON = 2, TX_AMP_LF_ON = 1, TX_AMP_OFF = 3 }; -      /************************************************************************       * Structors       ***********************************************************************/ -    UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(neon_radio_ctrl) -    virtual ~neon_radio_ctrl_impl(); +    e3xx_radio_ctrl_impl(); +    virtual ~e3xx_radio_ctrl_impl();      /************************************************************************       * API calls       ***********************************************************************/ +      // Note: We use the cached values in radio_ctrl_impl, so most getters are      // not reimplemented here - -    virtual bool check_radio_config(); +    //! Set streaming mode - active chains, channel_mode, timing_mode +    void set_streaming_mode( +        const bool tx1, const bool tx2, const bool rx1, const bool rx2);      //! Set which channel mode is used      void set_channel_mode(const std::string& channel_mode); -    //! Set streaming mode - active chains, channel_mode, timing_mode -    void set_streaming_mode( -        const bool tx1, const bool tx2, const bool rx1, const bool rx2); +    double set_rate(const double rate); + +    void set_tx_antenna(const std::string& ant, const size_t chan); +    void set_rx_antenna(const std::string& ant, const size_t chan); + +    double set_tx_frequency(const double freq, const size_t chan); +    double set_rx_frequency(const double freq, const size_t chan); +    double set_tx_bandwidth(const double bandwidth, const size_t chan); +    double set_rx_bandwidth(const double bandwidth, const size_t chan); + +    // gain +    double set_tx_gain(const double gain, const size_t chan); +    double set_rx_gain(const double gain, const size_t chan); + +    size_t get_chan_from_dboard_fe(const std::string& fe, const direction_t dir); +    std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); + +    void set_rpc_client(uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args); + +protected: +    //! Map a frequency in Hz to an rx_band value. Will return +    //  rx_band::INVALID_BAND if the frequency is out of range. +    rx_band map_freq_to_rx_band(const double freq); +    //! Map a frequency in Hz to an tx_band value. Will return +    //  tx_band::INVALID_BAND if the frequency is out of range. +    tx_band map_freq_to_tx_band(const double freq); + +    virtual const std::string get_default_timing_mode() = 0;      /*! Run a loopback self test.       * @@ -146,27 +113,27 @@ public:       *       * \throws a uhd::runtime_error if the loopback value didn't match.       */ -    void loopback_self_test(std::function<void(uint32_t)> poker_functor, -        std::function<uint64_t()> peeker_functor); +    virtual void loopback_self_test(std::function<void(uint32_t)> poker_functor, +        std::function<uint64_t()> peeker_functor) = 0; -    double set_rate(const double rate); +    virtual uint32_t get_rx_switches( +        const size_t chan, const double freq, const std::string& ant) = 0; -    void set_tx_antenna(const std::string& ant, const size_t chan); -    void set_rx_antenna(const std::string& ant, const size_t chan); +    virtual uint32_t get_tx_switches(const size_t chan, const double freq) = 0; -    double set_tx_frequency(const double freq, const size_t chan); -    double set_rx_frequency(const double freq, const size_t chan); -    double set_tx_bandwidth(const double bandwidth, const size_t chan); -    double set_rx_bandwidth(const double bandwidth, const size_t chan); +    virtual uint32_t get_idle_switches() = 0; -    // gain -    double set_tx_gain(const double gain, const size_t chan); -    double set_rx_gain(const double gain, const size_t chan); +    virtual uint32_t get_tx_led()   = 0; +    virtual uint32_t get_rx_led()   = 0; +    virtual uint32_t get_txrx_led() = 0; +    virtual uint32_t get_idle_led() = 0; -    size_t get_chan_from_dboard_fe(const std::string& fe, const direction_t dir); -    std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir); +    //! Reference to the AD9361 controls +    // e3xx_ad9361_iface::uptr _ad9361; +    ad9361_ctrl::sptr _ad9361; -    void set_rpc_client(uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args); +    //! Swap RFA and RFB for catalina +    bool _fe_swap;  private:      /************************************************************************** @@ -189,13 +156,6 @@ private:      void _init_mpm_sensors(const direction_t dir, const size_t chan_idx); -    //! Map a frequency in Hz to an rx_band value. Will return -    //  rx_band::INVALID_BAND if the frequency is out of range. -    rx_band _map_freq_to_rx_band(const double freq); -    //! Map a frequency in Hz to an tx_band value. Will return -    //  tx_band::INVALID_BAND if the frequency is out of range. -    tx_band _map_freq_to_tx_band(const double freq); -      /*************************************************************************       * Sensors       *************************************************************************/ @@ -210,11 +170,6 @@ private:      //  and resume normal operation.      void _identify_with_leds(const int identify_duration); -    uint32_t _get_rx_switches( -        const size_t chan, const double freq, const std::string& ant); - -    uint32_t _get_tx_switches(const size_t chan, const double freq); -      void _set_atr_bits(const size_t chan);      /************************************************************************** @@ -238,10 +193,6 @@ private:      //! Reference to the SPI core      uhd::spi_iface::sptr _spi; -    //! Reference to the AD9361 controls -    // neon_ad9361_iface::uptr _ad9361; -    ad9361_ctrl::sptr _ad9361; -      //! ATR controls. These control the AD9361 gain      //  up/down bits.      //  Every radio channel gets its own ATR state register. @@ -260,4 +211,5 @@ private:  }} /* namespace uhd::rfnoc */ -#endif /* INCLUDED_LIBUHD_RFNOC_NEON_RADIO_CTRL_IMPL_HPP */ +#endif /* INCLUDED_LIBUHD_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP */ +// vim: sw=4 et: diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_init.cpp index 783f0c7b2..5b33b33e7 100644 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_init.cpp +++ b/host/lib/usrp/dboard/e3xx/e3xx_radio_ctrl_init.cpp @@ -4,8 +4,8 @@  // SPDX-License-Identifier: GPL-3.0-or-later  // -#include "neon_constants.hpp" -#include "neon_radio_ctrl_impl.hpp" +#include "e3xx_constants.hpp" +#include "e3xx_radio_ctrl_impl.hpp"  #include <uhd/transport/chdr.hpp>  #include <uhd/types/eeprom.hpp>  #include <uhd/types/sensors.hpp> @@ -56,7 +56,7 @@ uint32_t _extract_port_number(      return radio_num * port_size + port_num;  } -void neon_radio_ctrl_impl::_init_defaults() +void e3xx_radio_ctrl_impl::_init_defaults()  {      UHD_LOG_TRACE(unique_id(), "Initializing defaults...");      const size_t num_rx_chans = get_output_ports().size(); @@ -66,17 +66,17 @@ void neon_radio_ctrl_impl::_init_defaults()          "Num TX chans: " << num_tx_chans << " Num RX chans: " << num_rx_chans);      for (size_t chan = 0; chan < num_rx_chans; chan++) { -        radio_ctrl_impl::set_rx_frequency(NEON_DEFAULT_FREQ, chan); -        radio_ctrl_impl::set_rx_gain(NEON_DEFAULT_GAIN, chan); -        radio_ctrl_impl::set_rx_antenna(NEON_DEFAULT_RX_ANTENNA, chan); -        radio_ctrl_impl::set_rx_bandwidth(NEON_DEFAULT_BANDWIDTH, chan); +        radio_ctrl_impl::set_rx_frequency(E3XX_DEFAULT_FREQ, chan); +        radio_ctrl_impl::set_rx_gain(E3XX_DEFAULT_GAIN, chan); +        radio_ctrl_impl::set_rx_antenna(E3XX_DEFAULT_RX_ANTENNA, chan); +        radio_ctrl_impl::set_rx_bandwidth(E3XX_DEFAULT_BANDWIDTH, chan);      }      for (size_t chan = 0; chan < num_tx_chans; chan++) { -        radio_ctrl_impl::set_tx_frequency(NEON_DEFAULT_FREQ, chan); -        radio_ctrl_impl::set_tx_gain(NEON_DEFAULT_GAIN, chan); -        radio_ctrl_impl::set_tx_antenna(NEON_DEFAULT_TX_ANTENNA, chan); -        radio_ctrl_impl::set_tx_bandwidth(NEON_DEFAULT_BANDWIDTH, chan); +        radio_ctrl_impl::set_tx_frequency(E3XX_DEFAULT_FREQ, chan); +        radio_ctrl_impl::set_tx_gain(E3XX_DEFAULT_GAIN, chan); +        radio_ctrl_impl::set_tx_antenna(E3XX_DEFAULT_TX_ANTENNA, chan); +        radio_ctrl_impl::set_tx_bandwidth(E3XX_DEFAULT_BANDWIDTH, chan);      }      /** Update default SPP (overwrites the default value from the XML file) **/ @@ -89,7 +89,7 @@ void neon_radio_ctrl_impl::_init_defaults()      _tree->access<int>(get_arg_path("spp") / "value").set(default_spp);  } -void neon_radio_ctrl_impl::_init_peripherals() +void e3xx_radio_ctrl_impl::_init_peripherals()  {      UHD_LOG_TRACE(unique_id(), "Initializing peripherals..."); @@ -115,7 +115,7 @@ void neon_radio_ctrl_impl::_init_peripherals()          _get_ctrl(0), regs::sr_addr(regs::FP_GPIO), regs::rb_addr(regs::RB_FP_GPIO));  } -void neon_radio_ctrl_impl::_init_frontend_subtree( +void e3xx_radio_ctrl_impl::_init_frontend_subtree(      uhd::property_tree::sptr subtree, const size_t chan_idx)  {      const fs_path tx_fe_path = fs_path("tx_frontends") / chan_idx; @@ -124,10 +124,10 @@ void neon_radio_ctrl_impl::_init_frontend_subtree(          "Adding non-RFNoC block properties for channel "              << chan_idx << " to prop tree path " << tx_fe_path << " and " << rx_fe_path);      // TX Standard attributes -    subtree->create<std::string>(tx_fe_path / "name").set(str(boost::format("Neon"))); +    subtree->create<std::string>(tx_fe_path / "name").set(str(boost::format("E3xx")));      subtree->create<std::string>(tx_fe_path / "connection").set("IQ");      // RX Standard attributes -    subtree->create<std::string>(rx_fe_path / "name").set(str(boost::format("Neon"))); +    subtree->create<std::string>(rx_fe_path / "name").set(str(boost::format("E3xx")));      subtree->create<std::string>(rx_fe_path / "connection").set("IQ");      // TX Antenna      subtree->create<std::string>(tx_fe_path / "antenna" / "value") @@ -136,7 +136,7 @@ void neon_radio_ctrl_impl::_init_frontend_subtree(          })          .set_publisher([this, chan_idx]() { return this->get_tx_antenna(chan_idx); });      subtree->create<std::vector<std::string>>(tx_fe_path / "antenna" / "options") -        .set({NEON_DEFAULT_TX_ANTENNA}) +        .set({E3XX_DEFAULT_TX_ANTENNA})          .add_coerced_subscriber([](const std::vector<std::string>&) {              throw uhd::runtime_error("Attempting to update antenna options!");          }); @@ -147,7 +147,7 @@ void neon_radio_ctrl_impl::_init_frontend_subtree(          })          .set_publisher([this, chan_idx]() { return this->get_rx_antenna(chan_idx); });      subtree->create<std::vector<std::string>>(rx_fe_path / "antenna" / "options") -        .set(NEON_RX_ANTENNAS) +        .set(E3XX_RX_ANTENNAS)          .add_coerced_subscriber([](const std::vector<std::string>&) {              throw uhd::runtime_error("Attempting to update antenna options!");          }); @@ -260,10 +260,10 @@ void neon_radio_ctrl_impl::_init_frontend_subtree(          });  } -void neon_radio_ctrl_impl::_init_prop_tree() +void e3xx_radio_ctrl_impl::_init_prop_tree()  {      const fs_path fe_base = fs_path("dboards") / _radio_slot; -    for (size_t chan_idx = 0; chan_idx < NEON_NUM_CHANS; chan_idx++) { +    for (size_t chan_idx = 0; chan_idx < E3XX_NUM_CHANS; chan_idx++) {          this->_init_frontend_subtree(_tree->subtree(fe_base), chan_idx);      } @@ -383,25 +383,25 @@ void neon_radio_ctrl_impl::_init_prop_tree()      }  } -void neon_radio_ctrl_impl::_init_codec() +void e3xx_radio_ctrl_impl::_init_codec()  {      for (size_t chan = 0; chan < _get_num_radios(); chan++) {          std::string rx_fe = get_which_ad9361_chain(RX_DIRECTION, chan); -        this->set_rx_gain(NEON_DEFAULT_GAIN, chan); -        this->set_rx_frequency(NEON_DEFAULT_FREQ, chan); -        this->set_rx_antenna(NEON_DEFAULT_RX_ANTENNA, chan); -        this->set_rx_bandwidth(NEON_DEFAULT_BANDWIDTH, chan); -        _ad9361->set_dc_offset_auto(rx_fe, NEON_DEFAULT_AUTO_DC_OFFSET); -        _ad9361->set_iq_balance_auto(rx_fe, NEON_DEFAULT_AUTO_IQ_BALANCE); -        _ad9361->set_agc(rx_fe, NEON_DEFAULT_AGC_ENABLE); +        this->set_rx_gain(E3XX_DEFAULT_GAIN, chan); +        this->set_rx_frequency(E3XX_DEFAULT_FREQ, chan); +        this->set_rx_antenna(E3XX_DEFAULT_RX_ANTENNA, chan); +        this->set_rx_bandwidth(E3XX_DEFAULT_BANDWIDTH, chan); +        _ad9361->set_dc_offset_auto(rx_fe, E3XX_DEFAULT_AUTO_DC_OFFSET); +        _ad9361->set_iq_balance_auto(rx_fe, E3XX_DEFAULT_AUTO_IQ_BALANCE); +        _ad9361->set_agc(rx_fe, E3XX_DEFAULT_AGC_ENABLE);          std::string tx_fe = get_which_ad9361_chain(TX_DIRECTION, chan); -        this->set_tx_gain(NEON_DEFAULT_GAIN, chan); -        this->set_tx_frequency(NEON_DEFAULT_FREQ, chan); -        this->set_tx_bandwidth(NEON_DEFAULT_BANDWIDTH, chan); +        this->set_tx_gain(E3XX_DEFAULT_GAIN, chan); +        this->set_tx_frequency(E3XX_DEFAULT_FREQ, chan); +        this->set_tx_bandwidth(E3XX_DEFAULT_BANDWIDTH, chan);      }  } -void neon_radio_ctrl_impl::_init_mpm_sensors(const direction_t dir, const size_t chan_idx) +void e3xx_radio_ctrl_impl::_init_mpm_sensors(const direction_t dir, const size_t chan_idx)  {      const std::string trx = (dir == RX_DIRECTION) ? "RX" : "TX";      const fs_path fe_path = fs_path("dboards") / _radio_slot diff --git a/host/lib/usrp/dboard/neon/CMakeLists.txt b/host/lib/usrp/dboard/neon/CMakeLists.txt deleted file mode 100644 index a2473bd0a..000000000 --- a/host/lib/usrp/dboard/neon/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright 2018 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -if(ENABLE_E320) -    list(APPEND NEON_SOURCES -        ${CMAKE_CURRENT_SOURCE_DIR}/neon_radio_ctrl_impl.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/neon_radio_ctrl_init.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/neon_ad9361_iface.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/neon_bands.cpp -    ) -    LIBUHD_APPEND_SOURCES(${NEON_SOURCES}) -endif(ENABLE_E320) diff --git a/host/lib/usrp/dboard/neon/neon_ad9361_iface.hpp b/host/lib/usrp/dboard/neon/neon_ad9361_iface.hpp deleted file mode 100644 index 1b7a48142..000000000 --- a/host/lib/usrp/dboard/neon/neon_ad9361_iface.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_LIBUHD_RFNOC_NEON_AD9361_IFACE_HPP -#define INCLUDED_LIBUHD_RFNOC_NEON_AD9361_IFACE_HPP - -#include <uhd/types/direction.hpp> -#include <uhd/types/filters.hpp> -#include <uhd/types/sensors.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> -#include <uhdlib/utils/rpc.hpp> -#include <memory> -#include <string> -#include <vector> - -using namespace uhd; -using namespace uhd::usrp; - -ad9361_ctrl::sptr make_rpc(rpc_client::sptr rpcc); -std::string get_which_ad9361_chain(const direction_t dir, const size_t chan); - -#endif /* INCLUDED_LIBUHD_RFNOC_NEON_AD9361_IFACE_HPP */ diff --git a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp b/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp deleted file mode 100644 index d8fabcee0..000000000 --- a/host/lib/usrp/dboard/neon/neon_radio_ctrl_impl.cpp +++ /dev/null @@ -1,563 +0,0 @@ -// -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "neon_radio_ctrl_impl.hpp" -#include "neon_constants.hpp" -#include "neon_regs.hpp" -#include <uhd/exception.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/transport/chdr.hpp> -#include <uhd/types/direction.hpp> -#include <uhd/types/eeprom.hpp> -#include <uhd/utils/algorithm.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/math.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/format.hpp> -#include <boost/make_shared.hpp> -#include <cmath> -#include <cstdlib> -#include <sstream> - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::rfnoc; -using namespace uhd::math::fp_compare; - -/****************************************************************************** - * Structors - *****************************************************************************/ -UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(neon_radio_ctrl) -{ -    UHD_LOG_TRACE(unique_id(), "Entering neon_radio_ctrl_impl ctor..."); -    const char radio_slot_name[1] = {'A'}; -    _radio_slot                   = radio_slot_name[get_block_id().get_block_count()]; -    UHD_LOG_TRACE(unique_id(), "Radio slot: " << _radio_slot); -    _rpc_prefix = "db_0_"; - -    _init_defaults(); -    _init_peripherals(); -    _init_prop_tree(); -} - -neon_radio_ctrl_impl::~neon_radio_ctrl_impl() -{ -    UHD_LOG_TRACE(unique_id(), "neon_radio_ctrl_impl::dtor() "); -} - - -/****************************************************************************** - * API Calls - *****************************************************************************/ - -bool neon_radio_ctrl_impl::check_radio_config() -{ -    // mapping of frontend to radio perif index -    static const size_t FE0 = 0; -    static const size_t FE1 = 1; -    const size_t num_rx = -        _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); -    const size_t num_tx = -        _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); - -    // setup the active chains in the codec -    if ((num_rx + num_tx) == 0) { -        // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock -        this->set_streaming_mode(false, false, true, false); -    } else { -        this->set_streaming_mode(_is_streamer_active(TX_DIRECTION, FE0), -            _is_streamer_active(TX_DIRECTION, FE1), -            _is_streamer_active(RX_DIRECTION, FE0), -            _is_streamer_active(RX_DIRECTION, FE1)); -    } -    return true; -} - -void neon_radio_ctrl_impl::set_streaming_mode( -    const bool tx1, const bool tx2, const bool rx1, const bool rx2) -{ -    UHD_LOG_TRACE(unique_id(), "Setting up streaming ...") -    const size_t num_rx = rx1 + rx2; -    const size_t num_tx = tx1 + tx2; - -    // setup the active chains in the codec -    _ad9361->set_active_chains(tx1, tx2, rx1, rx2); - -    const std::string TIMING_MODE_2R2T = "2R2T"; -    const std::string TIMING_MODE_1R1T = "1R1T"; -    const std::string MIMO             = "MIMO"; // 2R2T -    const std::string SISO_TX1         = "SISO_TX1"; // 1R1T -    const std::string SISO_TX0         = "SISO_TX0"; // 1R1T -    // setup 1R1T/2R2T mode in catalina and fpga -    // The Catalina interface in the fpga needs to know which TX channel to use for -    // the data on the LVDS lines. -    if ((num_rx == 2) or (num_tx == 2)) { -        // AD9361 is in 2R2T mode -        _ad9361->set_timing_mode(TIMING_MODE_2R2T); -        this->set_channel_mode(MIMO); -    } else { -        // AD9361 is in 1R1T mode -        _ad9361->set_timing_mode(TIMING_MODE_1R1T); - -        // Set to SIS0_TX1 if we're using the second TX antenna, otherwise -        // default to SISO_TX0 -        this->set_channel_mode(tx2 ? SISO_TX1 : SISO_TX0); -    } -} - -void neon_radio_ctrl_impl::set_channel_mode(const std::string& channel_mode) -{ -    // MIMO for 2R2T mode for 2 channels -    // SISO_TX1 for 1R1T mode for 1 channel - TX1 -    // SISO_TX0 for 1R1T mode for 1 channel - TX0 - -    _rpcc->request_with_token<void>("set_channel_mode", channel_mode); -} - -/*  loopback_self_test checks the integrity of the FPGA->AD936x->FPGA sample interface. -    The AD936x is put in loopback mode that sends the TX data unchanged to the RX side. -    A test value is written to the codec_idle register in the TX side of the radio. -    The readback register is then used to capture the values on the TX and RX sides -    simultaneously for comparison. It is a reasonably effective test for AC timing -    since I/Q Ch0/Ch1 alternate over the same wires. Note, however, that it uses -    whatever timing is configured at the time the test is called rather than select -    worst case conditions to stress the interface. -    Note: This currently only tests 2R2T mode -*/ -void neon_radio_ctrl_impl::loopback_self_test( -    std::function<void(uint32_t)> poker_functor, std::function<uint64_t()> peeker_functor) -{ -    // Save current rate before running this test -    const double current_rate = this->get_rate(); -    // Set 2R2T mode, stream on all channels -    this->set_streaming_mode(true, true, true, true); -    // Set maximum rate for 2R2T mode -    this->set_rate(30.72e6); -    // Put AD936x in loopback mode -    _ad9361->data_port_loopback(true); -    UHD_LOG_INFO(unique_id(), "Performing CODEC loopback test... "); -    size_t hash                     = size_t(time(NULL)); -    constexpr size_t loopback_count = 100; - -    // Allow some time for AD936x to enter loopback mode. -    // There is no clear statement in the documentation of how long it takes, -    // but UG-570 does say to "allow six ADC_CLK/64 clock cycles of flush time" -    // when leaving the TX or RX states.  That works out to ~75us at the -    // minimum clock rate of 5 MHz, which lines up with test results. -    // Sleeping 1ms is far more than enough. -    std::this_thread::sleep_for(std::chrono::milliseconds(1)); - -    for (size_t i = 0; i < loopback_count; i++) { -        // Create test word -        boost::hash_combine(hash, i); -        const uint32_t word32 = uint32_t(hash) & 0xfff0fff0; -        // const uint32_t word32 = 0xCA00C100; -        // Write test word to codec_idle idle register (on TX side) -        poker_functor(word32); - -        // Read back values - TX is lower 32-bits and RX is upper 32-bits -        const uint64_t rb_word64 = peeker_functor(); -        const uint32_t rb_tx     = uint32_t(rb_word64 >> 32); -        const uint32_t rb_rx     = uint32_t(rb_word64 & 0xffffffff); - -        // Compare TX and RX values to test word -        bool test_fail = word32 != rb_tx or word32 != rb_rx; -        if (test_fail) { -            UHD_LOG_WARNING(unique_id(), -                "CODEC loopback test failed! " -                    << boost::format("Expected: 0x%08X Received (TX/RX): 0x%08X/0x%08X") -                           % word32 % rb_tx % rb_rx); -            throw uhd::runtime_error("CODEC loopback test failed."); -        } -    } -    UHD_LOG_INFO(unique_id(), "CODEC loopback test passed"); - -    // Zero out the idle data. -    poker_functor(0); - -    // Take AD936x out of loopback mode -    _ad9361->data_port_loopback(false); -    this->set_streaming_mode(true, false, true, false); -    // Switch back to current rate -    this->set_rate(current_rate); -} - -double neon_radio_ctrl_impl::set_rate(const double rate) -{ -    std::lock_guard<std::mutex> l(_set_lock); -    UHD_LOG_DEBUG(unique_id(), "Asking for clock rate " << rate / 1e6 << " MHz\n"); -    double actual_tick_rate = _ad9361->set_clock_rate(rate); -    UHD_LOG_DEBUG( -        unique_id(), "Actual clock rate " << actual_tick_rate / 1e6 << " MHz\n"); - -    radio_ctrl_impl::set_rate(rate); -    return rate; -} - -void neon_radio_ctrl_impl::set_tx_antenna(const std::string& ant, const size_t chan) -{ -    if (ant != get_tx_antenna(chan)) { -        throw uhd::value_error( -            str(boost::format("[%s] Requesting invalid TX antenna value: %s") -                % unique_id() % ant)); -    } -    radio_ctrl_impl::set_tx_antenna(ant, chan); -    // We can't actually set the TX antenna, so let's stop here. -} - -void neon_radio_ctrl_impl::set_rx_antenna(const std::string& ant, const size_t chan) -{ -    UHD_ASSERT_THROW(chan <= NEON_NUM_CHANS); -    if (std::find(NEON_RX_ANTENNAS.begin(), NEON_RX_ANTENNAS.end(), ant) -        == NEON_RX_ANTENNAS.end()) { -        throw uhd::value_error( -            str(boost::format("[%s] Requesting invalid RX antenna value: %s") -                % unique_id() % ant)); -    } -    UHD_LOG_TRACE(unique_id(), "Setting RX antenna to " << ant << " for chan " << chan); - -    radio_ctrl_impl::set_rx_antenna(ant, chan); -    _set_atr_bits(chan); -} - -double neon_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t chan) -{ -    UHD_LOG_TRACE(unique_id(), "set_tx_frequency(f=" << freq << ", chan=" << chan << ")"); -    std::lock_guard<std::mutex> l(_set_lock); - -    double clipped_freq = uhd::clip(freq, AD9361_TX_MIN_FREQ, AD9361_TX_MAX_FREQ); - -    double coerced_freq = -        _ad9361->tune(get_which_ad9361_chain(TX_DIRECTION, chan), clipped_freq); -    radio_ctrl_impl::set_tx_frequency(coerced_freq, chan); -    // Front-end switching -    _set_atr_bits(chan); - -    return coerced_freq; -} - -double neon_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t chan) -{ -    UHD_LOG_TRACE(unique_id(), "set_rx_frequency(f=" << freq << ", chan=" << chan << ")"); -    std::lock_guard<std::mutex> l(_set_lock); - -    double clipped_freq = uhd::clip(freq, AD9361_RX_MIN_FREQ, AD9361_RX_MAX_FREQ); - -    double coerced_freq = -        _ad9361->tune(get_which_ad9361_chain(RX_DIRECTION, chan), clipped_freq); -    radio_ctrl_impl::set_rx_frequency(coerced_freq, chan); -    // Front-end switching -    _set_atr_bits(chan); - -    return coerced_freq; -} - -double neon_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) -{ -    std::lock_guard<std::mutex> l(_set_lock); -    double clipped_bw = -        _ad9361->set_bw_filter(get_which_ad9361_chain(RX_DIRECTION, chan), bandwidth); -    return radio_ctrl_impl::set_rx_bandwidth(clipped_bw, chan); -} - -double neon_radio_ctrl_impl::set_tx_bandwidth(const double bandwidth, const size_t chan) -{ -    std::lock_guard<std::mutex> l(_set_lock); -    double clipped_bw = -        _ad9361->set_bw_filter(get_which_ad9361_chain(TX_DIRECTION, chan), bandwidth); -    return radio_ctrl_impl::set_tx_bandwidth(clipped_bw, chan); -} - -double neon_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) -{ -    std::lock_guard<std::mutex> l(_set_lock); -    UHD_LOG_TRACE(unique_id(), "set_tx_gain(gain=" << gain << ", chan=" << chan << ")"); -    double clip_gain = uhd::clip(gain, AD9361_MIN_TX_GAIN, AD9361_MAX_TX_GAIN); -    _ad9361->set_gain(get_which_ad9361_chain(TX_DIRECTION, chan), clip_gain); -    radio_ctrl_impl::set_tx_gain(clip_gain, chan); -    return clip_gain; -} - -double neon_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) -{ -    std::lock_guard<std::mutex> l(_set_lock); -    UHD_LOG_TRACE(unique_id(), "set_rx_gain(gain=" << gain << ", chan=" << chan << ")"); -    double clip_gain = uhd::clip(gain, AD9361_MIN_RX_GAIN, AD9361_MAX_RX_GAIN); -    _ad9361->set_gain(get_which_ad9361_chain(RX_DIRECTION, chan), clip_gain); -    radio_ctrl_impl::set_rx_gain(clip_gain, chan); -    return clip_gain; -} - -size_t neon_radio_ctrl_impl::get_chan_from_dboard_fe( -    const std::string& fe, const direction_t /* dir */ -) -{ -    const size_t chan = boost::lexical_cast<size_t>(fe); -    if (chan > _get_num_radios() - 1) { -        UHD_LOG_WARNING(unique_id(), -            boost::format("Invalid channel determined from dboard frontend %s.") % fe); -    } -    return chan; -} - -std::string neon_radio_ctrl_impl::get_dboard_fe_from_chan( -    const size_t chan, const direction_t /* dir */ -) -{ -    return std::to_string(chan); -} - -void neon_radio_ctrl_impl::set_rpc_client( -    uhd::rpc_client::sptr rpcc, const uhd::device_addr_t& block_args) -{ -    _rpcc       = rpcc; -    _block_args = block_args; -    UHD_LOG_TRACE(unique_id(), "Instantiating AD9361 control object..."); -    _ad9361 = make_rpc(_rpcc); - -    UHD_LOG_TRACE(unique_id(), "Setting Catalina Defaults... "); -    // Initialize catalina -    this->_init_codec(); - -    if (block_args.has_key("identify")) { -        const std::string identify_val = block_args.get("identify"); -        int identify_duration          = std::atoi(identify_val.c_str()); -        if (identify_duration == 0) { -            identify_duration = 5; -        } -        UHD_LOG_INFO(unique_id(), -            "Running LED identification process for " << identify_duration -                                                      << " seconds."); -        _identify_with_leds(identify_duration); -    } -    // Note: MCR gets set during the init() call (prior to this), which takes -    // in arguments from the device args. So if block_args contains a -    // master_clock_rate key, then it should better be whatever the device is -    // configured to do. -    _master_clock_rate = -        _rpcc->request_with_token<double>(_rpc_prefix + "get_master_clock_rate"); -    if (block_args.cast<double>("master_clock_rate", _master_clock_rate) -        != _master_clock_rate) { -        throw uhd::runtime_error(str( -            boost::format("Master clock rate mismatch. Device returns %f MHz, " -                          "but should have been %f MHz.") -            % (_master_clock_rate / 1e6) -            % (block_args.cast<double>("master_clock_rate", _master_clock_rate) / 1e6))); -    } -    UHD_LOG_DEBUG( -        unique_id(), "Master Clock Rate is: " << (_master_clock_rate / 1e6) << " MHz."); -    this->set_rate(_master_clock_rate); - -    // Loopback test -    for (size_t chan = 0; chan < _get_num_radios(); chan++) { -        loopback_self_test( -            [this, chan]( -                const uint32_t value) { this->sr_write(regs::CODEC_IDLE, value, chan); }, -            [this, chan]() { -                return this->user_reg_read64(regs::RB_CODEC_READBACK, chan); -            }); -    } - -    const size_t db_idx = get_block_id().get_block_count(); -    _tree->access<eeprom_map_t>(_root_path / "eeprom") -        .add_coerced_subscriber([this, db_idx](const eeprom_map_t& db_eeprom) { -            this->_rpcc->notify_with_token("set_db_eeprom", db_idx, db_eeprom); -        }) -        .set_publisher([this, db_idx]() { -            return this->_rpcc->request_with_token<eeprom_map_t>("get_db_eeprom", db_idx); -        }); - -    // Init sensors -    for (const auto& dir : std::vector<direction_t>{RX_DIRECTION, TX_DIRECTION}) { -        for (size_t chan_idx = 0; chan_idx < NEON_NUM_CHANS; chan_idx++) { -            _init_mpm_sensors(dir, chan_idx); -        } -    } -} - -bool neon_radio_ctrl_impl::get_lo_lock_status(const direction_t dir) -{ -    if (not(bool(_rpcc))) { -        UHD_LOG_DEBUG(unique_id(), "Reported no LO lock due to lack of RPC connection."); -        return false; -    } - -    const std::string trx = (dir == RX_DIRECTION) ? "rx" : "tx"; -    bool lo_lock = -        _rpcc->request_with_token<bool>(_rpc_prefix + "get_ad9361_lo_lock", trx); -    UHD_LOG_TRACE(unique_id(), -        "AD9361 " << trx << " LO reports lock: " << (lo_lock ? "Yes" : "No")); - -    return lo_lock; -} - -void neon_radio_ctrl_impl::_set_atr_bits(const size_t chan) -{ -    const auto rx_freq       = radio_ctrl_impl::get_rx_frequency(chan); -    const auto tx_freq       = radio_ctrl_impl::get_tx_frequency(chan); -    const auto rx_ant        = radio_ctrl_impl::get_rx_antenna(chan); -    const uint32_t rx_regs   = _get_rx_switches(chan, rx_freq, rx_ant); -    const uint32_t tx_regs   = _get_tx_switches(chan, tx_freq); -    const uint32_t idle_regs = TX_AMP_OFF << TX_AMP_SHIFT | TRX1_SW_TX_HB << TRX_SW_SHIFT -                               | TX_SW2_LB_80 << TX_SW2_SHIFT -                               | TX_SW1_LB_80 << TX_SW1_SHIFT | RX_SW3_OFF << RX_SW3_SHIFT -                               | RX_SW2_OFF << RX_SW2_SHIFT | RX_SW1_OFF << RX_SW1_SHIFT; - -    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_regs); -    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, rx_regs); -    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_regs); -    _db_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, rx_regs | tx_regs); - -    // The LED signal names are reversed, but are consistent with the schematic -    const int idle_led = 0; -    const bool is_txrx = rx_ant == "TX/RX"; -    const int rx_led   = 1 << TRX_LED_GRN_SHIFT; -    const int tx_led   = 1 << TX_LED_RED_SHIFT; -    const int txrx_led = 1 << RX_LED_GRN_SHIFT; - -    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, idle_led); -    _leds_gpio[chan]->set_atr_reg( -        usrp::gpio_atr::ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led); -    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_led); -    _leds_gpio[chan]->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, rx_led | tx_led); -} - -void neon_radio_ctrl_impl::_identify_with_leds(const int identify_duration) -{ -    auto end_time = -        std::chrono::steady_clock::now() + std::chrono::seconds(identify_duration); -    bool led_state = true; -    while (std::chrono::steady_clock::now() < end_time) { -        // Add update_leds -        led_state = !led_state; -        std::this_thread::sleep_for(std::chrono::milliseconds(500)); -    } -} - -uint32_t neon_radio_ctrl_impl::_get_tx_switches(const size_t chan, const double freq) -{ -    UHD_LOG_TRACE( -        unique_id(), "Update all TX freq related switches. f=" << freq << " Hz, "); -    auto tx_sw1 = TX_SW1_LB_160; -    auto tx_sw2 = TX_SW2_LB_160; -    auto trx_sw = (chan == 0) ? TRX1_SW_TX_LB : TRX2_SW_TX_LB; -    auto tx_amp = TX_AMP_LF_ON; - -    const auto band = _map_freq_to_tx_band(freq); -    switch (band) { -        case tx_band::LB_80: -            tx_sw1 = TX_SW1_LB_80; -            tx_sw2 = TX_SW2_LB_80; -            break; -        case tx_band::LB_160: -            tx_sw1 = TX_SW1_LB_160; -            tx_sw2 = TX_SW2_LB_160; -            break; -        case tx_band::LB_225: -            tx_sw1 = TX_SW1_LB_225; -            tx_sw2 = TX_SW2_LB_225; -            break; -        case tx_band::LB_400: -            tx_sw1 = TX_SW1_LB_400; -            tx_sw2 = TX_SW2_LB_400; -            break; -        case tx_band::LB_575: -            tx_sw1 = TX_SW1_LB_575; -            tx_sw2 = TX_SW2_LB_575; -            break; -        case tx_band::LB_1000: -            tx_sw1 = TX_SW1_LB_1000; -            tx_sw2 = TX_SW2_LB_1000; -            break; -        case tx_band::LB_1700: -            tx_sw1 = TX_SW1_LB_1700; -            tx_sw2 = TX_SW2_LB_1700; -            break; -        case tx_band::LB_2750: -            tx_sw1 = TX_SW1_LB_2750; -            tx_sw2 = TX_SW2_LB_2750; -            break; -        case tx_band::HB: -            trx_sw = (chan == 0) ? TRX1_SW_TX_HB : TRX2_SW_TX_HB; -            tx_amp = TX_AMP_HF_ON; -            break; -        case tx_band::INVALID_BAND: -            UHD_LOG_ERROR(unique_id(), "Cannot map TX frequency to band: " << freq); -            UHD_THROW_INVALID_CODE_PATH(); -            break; -    } - -    auto tx_regs = tx_amp << TX_AMP_SHIFT | trx_sw << TRX_SW_SHIFT -                   | tx_sw2 << TX_SW2_SHIFT | tx_sw1 << TX_SW1_SHIFT; -    return tx_regs; -} - -uint32_t neon_radio_ctrl_impl::_get_rx_switches( -    const size_t chan, const double freq, const std::string& ant) -{ -    UHD_LOG_TRACE( -        unique_id(), "Update all RX freq related switches. f=" << freq << " Hz, "); -    // Default to OFF -    auto rx_sw1 = RX_SW1_OFF; -    auto rx_sw2 = RX_SW2_OFF; -    auto rx_sw3 = RX_SW3_OFF; -    auto trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; -    if (ant == "TX/RX") { -        rx_sw3 = RX_SW3_HBRX_LBTRX; -        trx_sw = (chan == 0) ? TRX1_SW_RX : TRX2_SW_RX; -    } else if (ant == "RX2") { -        rx_sw3 = RX_SW3_HBTRX_LBRX; -        // Set TRX switch to TX when receiving on RX2 -        trx_sw = TRX1_SW_TX_HB; -    } - -    const auto band = _map_freq_to_rx_band(freq); -    switch (band) { -        case rx_band::LB_B2: -            rx_sw1 = RX_SW1_LB_B2; -            rx_sw2 = RX_SW2_LB_B2; -            break; -        case rx_band::LB_B3: -            rx_sw1 = RX_SW1_LB_B3; -            rx_sw2 = RX_SW2_LB_B3; -            break; -        case rx_band::LB_B4: -            rx_sw1 = RX_SW1_LB_B4; -            rx_sw2 = RX_SW2_LB_B4; -            break; -        case rx_band::LB_B5: -            rx_sw1 = RX_SW1_LB_B5; -            rx_sw2 = RX_SW2_LB_B5; -            break; -        case rx_band::LB_B6: -            rx_sw1 = RX_SW1_LB_B6; -            rx_sw2 = RX_SW2_LB_B6; -            break; -        case rx_band::LB_B7: -            rx_sw1 = RX_SW1_LB_B7; -            rx_sw2 = RX_SW2_LB_B7; -            break; -        case rx_band::HB: -            rx_sw1 = RX_SW1_OFF; -            rx_sw2 = RX_SW2_OFF; -            if (ant == "TX/RX") { -                rx_sw3 = RX_SW3_HBTRX_LBRX; -            } else if (ant == "RX2") { -                rx_sw3 = RX_SW3_HBRX_LBTRX; -            } -            break; -        case rx_band::INVALID_BAND: -            UHD_LOG_ERROR(unique_id(), "Cannot map RX frequency to band: " << freq); -            UHD_THROW_INVALID_CODE_PATH(); -            break; -    } - -    auto rx_regs = trx_sw << TRX_SW_SHIFT | rx_sw3 << RX_SW3_SHIFT -                   | rx_sw2 << RX_SW2_SHIFT | rx_sw1 << RX_SW1_SHIFT; -    return rx_regs; -} - -UHD_RFNOC_BLOCK_REGISTER(neon_radio_ctrl, "NeonRadio"); diff --git a/host/lib/usrp/e300/CMakeLists.txt b/host/lib/usrp/e300/CMakeLists.txt deleted file mode 100644 index 9821fe34a..000000000 --- a/host/lib/usrp/e300/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# Copyright 2013-2015 Ettus Research LLC -# Copyright 2018 Ettus Research, a National Instruments Company -# -# SPDX-License-Identifier: GPL-3.0-or-later -# - -######################################################################## -# This file included, use CMake directory variables -######################################################################## - -######################################################################## -# Conditionally configure the USRP-E300 support -######################################################################## -find_package(UDev) - -if(ENABLE_E300) -    list(APPEND E300_SOURCES -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_impl.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_io_impl.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_fifo_config.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_sysfs_hooks.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_network.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_global_regs.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_spi.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_sensor_manager.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_i2c.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_eeprom_manager.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_common.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e300_remote_codec_ctrl.cpp -        ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_radio_ctrl_impl.cpp -    ) -    LIBUHD_APPEND_SOURCES(${E300_SOURCES}) -    if(UDEV_FOUND AND NOT E300_FORCE_NETWORK) -        include_directories(${UDEV_INCLUDE_DIR}) -        LIBUHD_APPEND_LIBS(${UDEV_LIBS}) -        set_source_files_properties( -            ${E300_SOURCES} -            PROPERTIES COMPILE_DEFINITIONS "E300_NATIVE=1" -        ) -    endif(UDEV_FOUND AND NOT E300_FORCE_NETWORK) - -    if(ENABLE_GPSD) -        set_source_files_properties( -            ${CMAKE_CURRENT_SOURCE_DIR}/e300_impl.cpp -            ${CMAKE_CURRENT_SOURCE_DIR}/e300_impl.hpp -            ${CMAKE_CURRENT_SOURCE_DIR}/e3xx_radio_ctrl_impl.cpp -            PROPERTIES COMPILE_DEFINITIONS "E300_GPSD=1" -        ) -    endif(ENABLE_GPSD) -endif(ENABLE_E300) diff --git a/host/lib/usrp/e300/e300_common.cpp b/host/lib/usrp/e300/e300_common.cpp deleted file mode 100644 index cd52bb9d0..000000000 --- a/host/lib/usrp/e300/e300_common.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// -#include <uhd/image_loader.hpp> -#include <uhd/utils/log.hpp> -#include <uhd/utils/paths.hpp> -#include <uhd/utils/static.hpp> - -#include "e300_impl.hpp" -#include "e300_fifo_config.hpp" -#include "e300_fifo_config.hpp" - -#include "e300_common.hpp" - -#include <boost/filesystem.hpp> -#include <fstream> -#include <string> - -#ifdef E300_NATIVE -namespace uhd { namespace usrp { namespace e300 { - -namespace common { - -void load_fpga_image(const std::string &path) -{ -    if (not boost::filesystem::exists("/dev/xdevcfg")) -        ::system("mknod /dev/xdevcfg c 259 0"); - -    UHD_LOGGER_INFO("E300") << "Loading FPGA image: " << path << "..."; - -    std::ifstream fpga_file(path.c_str(), std::ios_base::binary); -    UHD_ASSERT_THROW(fpga_file.good()); - -    std::FILE *wfile; -    wfile = std::fopen("/dev/xdevcfg", "wb"); -    UHD_ASSERT_THROW(!(wfile == NULL)); - -    char buff[16384]; // devcfg driver can't handle huge writes -    do { -        fpga_file.read(buff, sizeof(buff)); -        std::fwrite(buff, 1, size_t(fpga_file.gcount()), wfile); -    } while (fpga_file); - -    fpga_file.close(); -    std::fclose(wfile); - -    UHD_LOGGER_INFO("E300") << "FPGA image loaded"; -} - -static bool e300_image_loader(const image_loader::image_loader_args_t &image_loader_args) { -    // Make sure this is an E3x0 and we don't want to use anything connected -    uhd::device_addrs_t devs = e300_find(image_loader_args.args); -    if(devs.size() == 0 or !image_loader_args.load_fpga) return false; - -    std::string fpga_filename, idle_image; // idle_image never used, just needed for function -    if(image_loader_args.fpga_path == "") { -        get_e3x0_fpga_images(devs[0], fpga_filename, idle_image); -    } -    else { -        if(not boost::filesystem::exists(image_loader_args.fpga_path)) { -            throw uhd::runtime_error(str(boost::format("The path \"%s\" does not exist.") -                                         % image_loader_args.fpga_path)); -        } -        else fpga_filename = image_loader_args.fpga_path; -    } - -    load_fpga_image(fpga_filename); -    return true; -} - -UHD_STATIC_BLOCK(register_e300_image_loader) { -    std::string recovery_instructions = "The default FPGA image will be loaded the next " -                                        "time UHD uses this device."; - -    image_loader::register_image_loader("e3x0", e300_image_loader, recovery_instructions); -} - -} - -}}} - -#else -namespace uhd { namespace usrp { namespace e300 { - -namespace common { - -void load_fpga_image(const std::string&) -{ -    throw uhd::assertion_error("load_fpga_image() !E300_NATIVE"); -} - -} - -}}} -#endif diff --git a/host/lib/usrp/e300/e300_common.hpp b/host/lib/usrp/e300/e300_common.hpp deleted file mode 100644 index 8624f0e3c..000000000 --- a/host/lib/usrp/e300/e300_common.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_COMMON_HPP -#define INCLUDED_E300_COMMON_HPP - -namespace uhd { namespace usrp { namespace e300 { - -namespace common { - -void load_fpga_image(const std::string &path); - -}; - -}}} - -#endif // INCLUDED_E300_COMMON_HPP diff --git a/host/lib/usrp/e300/e300_defaults.hpp b/host/lib/usrp/e300/e300_defaults.hpp deleted file mode 100644 index 97b0ddc3f..000000000 --- a/host/lib/usrp/e300/e300_defaults.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_DEFAULTS_HPP -#define INCLUDED_E300_DEFAULTS_HPP - -#include "ad9361_client.h" - -namespace uhd { namespace usrp { namespace e300 { - -static const double DEFAULT_TICK_RATE       = 32e6; -static const double MIN_TICK_RATE           = 10e6; - -static const double DEFAULT_TX_SAMP_RATE    = 1.0e6; -static const double DEFAULT_RX_SAMP_RATE    = 1.0e6; -static const double DEFAULT_DDC_FREQ        = 0.0; -static const double DEFAULT_DUC_FREQ        = 0.0; - -static const std::string DEFAULT_TIME_SRC   = "internal"; -static const std::string DEFAULT_CLOCK_SRC  = "internal"; - -static const size_t DEFAULT_RX_DATA_FRAME_SIZE = 4096; -static const size_t DEFAULT_RX_DATA_NUM_FRAMES = 32; - -static const size_t DEFAULT_TX_DATA_FRAME_SIZE = 4096; -static const size_t DEFAULT_TX_DATA_NUM_FRAMES = 32; - -static const size_t DEFAULT_CTRL_FRAME_SIZE    = 64; -static const size_t DEFAULT_CTRL_NUM_FRAMES    = 32; - -static const size_t MAX_NET_RX_DATA_FRAME_SIZE = 1200; -static const size_t MAX_NET_TX_DATA_FRAME_SIZE = 1200; - -static const size_t MAX_AXI_RX_DATA_FRAME_SIZE = 4096; -static const size_t MAX_AXI_TX_DATA_FRAME_SIZE = 4096; - -static const size_t MAX_DMA_CHANNEL_PAIRS = 16; - -static const double AD9361_SPI_RATE = 8e6; - -class e300_ad9361_client_t : public ad9361_params { -public: -    ~e300_ad9361_client_t() {} -    double get_band_edge(frequency_band_t band) { -        switch (band) { -        case AD9361_RX_BAND0:   return 1.2e9; -        case AD9361_RX_BAND1:   return 2.6e9; -        case AD9361_TX_BAND0:   return 2940.0e6; -        default:                return 0; -        } -    } -    clocking_mode_t get_clocking_mode() { -        return clocking_mode_t::AD9361_XTAL_N_CLK_PATH; -    } -    digital_interface_mode_t get_digital_interface_mode() { -        return AD9361_DDR_FDD_LVCMOS; -    } -    digital_interface_delays_t get_digital_interface_timing() { -        digital_interface_delays_t delays; -        delays.rx_clk_delay = 0; -        delays.rx_data_delay = 0xF; -        delays.tx_clk_delay = 0; -        delays.tx_data_delay = 0xF; -        return delays; -    } -}; - -}}} // namespace - -#endif // INCLUDED_E300_DEFAULTS_HPP diff --git a/host/lib/usrp/e300/e300_eeprom_manager.cpp b/host/lib/usrp/e300/e300_eeprom_manager.cpp deleted file mode 100644 index 6547048ec..000000000 --- a/host/lib/usrp/e300/e300_eeprom_manager.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_eeprom_manager.hpp" -#include <uhd/types/mac_addr.hpp> -#include <uhd/utils/byteswap.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -static const std::string _bytes_to_string(const uint8_t* bytes, size_t max_len) -{ -    std::string out; -    for (size_t i = 0; i < max_len; i++) { -        if (bytes[i] < 32 or bytes[i] > 127) return out; -        out += bytes[i]; -    } -    return out; -} - -static void _string_to_bytes(const std::string &string, size_t max_len, uint8_t* buffer) -{ -    byte_vector_t bytes; -    const size_t len = std::min(string.size(), max_len); -    for (size_t i = 0; i < len; i++){ -        buffer[i] = string[i]; -    } -    if (len < max_len) -        buffer[len] = '\0'; -} - -e300_eeprom_manager::e300_eeprom_manager(i2c::sptr i2c) : _i2c(i2c) -{ -    read_mb_eeprom(); -    read_db_eeprom(); -} - -e300_eeprom_manager::~e300_eeprom_manager(void) -{ -} - -const mboard_eeprom_t& e300_eeprom_manager::read_mb_eeprom(void) -{ -    boost::mutex::scoped_lock(_mutex); - -    std::vector<uint8_t> bytes; -    bytes.resize(sizeof(mb_eeprom_map_t)); -    mb_eeprom_map_t *map_ptr = reinterpret_cast<mb_eeprom_map_t*>(&bytes[0]); -    memset(map_ptr, 0xff, sizeof(mb_eeprom_map_t)); - -    // get the old contents -    for(size_t i = 0; i < sizeof(mb_eeprom_map_t); i++) -        bytes[i] = _i2c->get_i2c_reg8(MB_ADDR, i); - -    mb_eeprom_map_t &map = *map_ptr; - -    _mb_eeprom["product"] = std::to_string( -        uhd::ntohx<uint16_t>(map.hw_product)); -    _mb_eeprom["revision"] = std::to_string( -        uhd::ntohx<uint16_t>(map.hw_revision)); -    _mb_eeprom["serial"] = _bytes_to_string( -        map.serial, MB_SERIAL_LEN); - -    byte_vector_t mac_addr(map.mac_addr, map.mac_addr + 6); -    _mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(mac_addr).to_string(); - -    _mb_eeprom["name"] = _bytes_to_string( -        map.user_name, MB_NAME_LEN); - -    return _mb_eeprom; -} - -const dboard_eeprom_t& e300_eeprom_manager::read_db_eeprom(void) -{ -    boost::mutex::scoped_lock(_mutex); - -    std::vector<uint8_t> bytes; -    bytes.resize(sizeof(db_eeprom_map_t)); -    db_eeprom_map_t *map_ptr = reinterpret_cast<db_eeprom_map_t*>(&bytes[0]); -    memset(map_ptr, 0xff, sizeof(db_eeprom_map_t)); - -    // get the old contents -    for(size_t i = 0; i < sizeof(db_eeprom_map_t); i++) -        bytes[i] = _i2c->get_i2c_reg16(DB_ADDR, i); - -    db_eeprom_map_t &map = *map_ptr; - -    _db_eeprom.id = uhd::usrp::dboard_id_t::from_uint16( -        uhd::ntohx<uint16_t>(map.hw_product)); - -    _db_eeprom.revision = std::to_string( -        uhd::ntohx<uint16_t>(map.hw_revision)); -    _db_eeprom.serial = _bytes_to_string( -        map.serial, DB_SERIAL_LEN); - -    return _db_eeprom; -} - -void e300_eeprom_manager::write_db_eeprom(const dboard_eeprom_t& eeprom) -{ -    boost::mutex::scoped_lock(_mutex); -    _db_eeprom = eeprom; -    std::vector<uint8_t> bytes; -    bytes.resize(sizeof(db_eeprom_map_t)); - - -    db_eeprom_map_t *map_ptr = reinterpret_cast<db_eeprom_map_t*>(&bytes[0]); -    memset(map_ptr, 0xff, sizeof(db_eeprom_map_t)); - -    // get the old contents -    for(size_t i = 0; i < sizeof(db_eeprom_map_t); i++) -        bytes[i] = _i2c->get_i2c_reg16(DB_ADDR, i); - -    db_eeprom_map_t &map = *map_ptr; - -    // set the data version, that can be used to distinguish eeprom layouts -    map.data_version_major = E310_DB_MAP_MAJOR; -    map.data_version_minor = E310_DB_MAP_MINOR; - -    if (_db_eeprom.id != dboard_id_t::none()) { -        map.hw_product = uhd::htonx<uint16_t>( -            _db_eeprom.id.to_uint16()); -    } - -    if (not _db_eeprom.revision.empty()) { -        map.hw_revision = uhd::htonx<uint16_t>( -            boost::lexical_cast<uint16_t>(_db_eeprom.revision)); -    } - -    if (not _db_eeprom.serial.empty()) { -        _string_to_bytes(_db_eeprom.serial, DB_SERIAL_LEN, map.serial); -    } -    for(size_t i = 0; i < sizeof(mb_eeprom_map_t); i++) -        _i2c->set_i2c_reg16(DB_ADDR, i, bytes[i]); -} - -void e300_eeprom_manager::write_mb_eeprom(const mboard_eeprom_t& eeprom) -{ -    boost::mutex::scoped_lock(_mutex); -    _mb_eeprom = eeprom; -    std::vector<uint8_t> bytes; -    bytes.resize(sizeof(mb_eeprom_map_t)); - - -    mb_eeprom_map_t *map_ptr = reinterpret_cast<mb_eeprom_map_t*>(&bytes[0]); -    memset(map_ptr, 0xff, sizeof(mb_eeprom_map_t)); - -    // get the old contents -    for(size_t i = 0; i < sizeof(mb_eeprom_map_t); i++) -        bytes[i] = _i2c->get_i2c_reg8(MB_ADDR, i); - -    mb_eeprom_map_t &map = *map_ptr; - -    // set the data version, that can be used to distinguish eeprom layouts -    map.data_version_major = E310_MB_MAP_MAJOR; -    map.data_version_minor = E310_MB_MAP_MINOR; - - -    if (_mb_eeprom.has_key("product")) { -        map.hw_product = uhd::htonx<uint16_t>( -            boost::lexical_cast<uint16_t>(_mb_eeprom["product"])); -    } -    if (_mb_eeprom.has_key("revision")) { -        map.hw_revision = uhd::htonx<uint16_t>( -            boost::lexical_cast<uint16_t>(_mb_eeprom["revision"])); -    } -    if (_mb_eeprom.has_key("serial")) { -        _string_to_bytes(_mb_eeprom["serial"], MB_SERIAL_LEN, map.serial); -    } -    if (_mb_eeprom.has_key("mac-addr")) { -        byte_vector_t mac_addr = mac_addr_t::from_string(_mb_eeprom["mac-addr"]).to_bytes(); -        std::copy(mac_addr.begin(), mac_addr.end(), map.mac_addr); -    } - -    //store the name -    if (_mb_eeprom.has_key("name")) { -        _string_to_bytes(_mb_eeprom["name"], MB_NAME_LEN, map.user_name); -    } - -    for(size_t i = 0; i < sizeof(mb_eeprom_map_t); i++) -        _i2c->set_i2c_reg8(MB_ADDR, i, bytes[i]); - -} - -e300_eeprom_manager::mboard_t e300_eeprom_manager::get_mb_type(void) const -{ -    boost::mutex::scoped_lock(_mutex); -    uint16_t pid = boost::lexical_cast<uint16_t>( -        _mb_eeprom["product"]); -    return get_mb_type(pid); -} - -e300_eeprom_manager::mboard_t e300_eeprom_manager::get_mb_type( -    uint16_t pid) -{ -    switch (pid) { -    case E300_MB_PID: -        return USRP_E300_MB; - -    case E310_SG1_MB_PID: -        return USRP_E310_SG1_MB; - -    case E310_SG3_MB_PID: -        return USRP_E310_SG3_MB; - -    default: -        return UNKNOWN; -    }; -} - - -std::string e300_eeprom_manager::get_mb_type_string(void) const -{ -    boost::mutex::scoped_lock(_mutex); -    uint16_t product = boost::lexical_cast<uint16_t>( -        _mb_eeprom["product"]); -    switch (product) { -    case E300_MB_PID: -        return "E3XX"; - -    case E310_SG1_MB_PID: -        return "E3XX SG1"; - -    case E310_SG3_MB_PID: -        return "E3XX SG3"; - -    default: -        return "UNKNOWN"; -    }; -} - -i2c::sptr e300_eeprom_manager::get_i2c_sptr(void) -{ -    return _i2c; -} - - -}}} // namespace diff --git a/host/lib/usrp/e300/e300_eeprom_manager.hpp b/host/lib/usrp/e300/e300_eeprom_manager.hpp deleted file mode 100644 index ee4497211..000000000 --- a/host/lib/usrp/e300/e300_eeprom_manager.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_EEPROM_MANAGER_HPP -#define INCLUDED_E300_EEPROM_MANAGER_HPP - -#include <boost/thread/mutex.hpp> -#include <boost/shared_ptr.hpp> -#include <uhd/types/dict.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> - -#include "e300_i2c.hpp" - -namespace uhd { namespace usrp { namespace e300 { - -static const uint16_t E300_MB_PID = 0x77d1; -static const uint16_t E310_SG1_MB_PID = 0x77d2; -static const uint16_t E310_SG3_MB_PID = 0x77d3; - -static const uint16_t E300_DB_PID = 0x0100; -static const uint16_t E310_DB_PID = 0x0110; - -static const uint16_t E310_MB_MAP_MAJOR = 0x0001; -static const uint16_t E310_MB_MAP_MINOR = 0x0000; - -static const uint16_t E310_DB_MAP_MAJOR = 0x0001; -static const uint16_t E310_DB_MAP_MINOR = 0x0000; - -class e300_eeprom_manager : uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<e300_eeprom_manager> sptr; -    e300_eeprom_manager(i2c::sptr i2c); -    ~e300_eeprom_manager(); - -    // mboard -    const mboard_eeprom_t& read_mb_eeprom(); -    void write_mb_eeprom(const mboard_eeprom_t& eeprom); - -    UHD_INLINE const mboard_eeprom_t& get_mb_eeprom() -    { -        return _mb_eeprom; -    } - -    // dboard -    const dboard_eeprom_t& read_db_eeprom(); -    void write_db_eeprom(const dboard_eeprom_t& eeprom); - -    UHD_INLINE const dboard_eeprom_t& get_db_eeprom() -    { -        return _db_eeprom; -    } - - -    i2c::sptr get_i2c_sptr(void); - -    enum mboard_t {USRP_E300_MB, USRP_E310_SG1_MB, USRP_E310_SG3_MB, UNKNOWN}; - -    mboard_t get_mb_type(void) const; -    static mboard_t get_mb_type(uint16_t pid); -    std::string get_mb_type_string(void) const; - -private: // types -    const static size_t MB_SERIAL_LEN = 8; -    const static size_t MB_NAME_LEN   = 32; -    const static size_t MB_ADDR       = 0x51; - -    const static size_t DB_SERIAL_LEN = 8; -    const static size_t DB_ADDR       = 0x50; - -    struct mb_eeprom_map_t -    { -        // Data format version -        uint16_t data_version_major; -        uint16_t data_version_minor; - -        // NIC mac address -        uint8_t mac_addr[6]; - -        // HW identification info -        uint16_t hw_product; -        uint16_t hw_revision; - -        // serial -        uint8_t serial[MB_SERIAL_LEN]; -        uint8_t pad[20 - MB_SERIAL_LEN]; - -        //User specific -        uint8_t user_name[MB_NAME_LEN]; -    }; - -    struct db_eeprom_map_t -    { -        // Data format version -        uint16_t data_version_major; -        uint16_t data_version_minor; - -        // HW identification info -        uint16_t hw_product; -        uint16_t hw_revision; - -        // serial -        uint8_t serial[DB_SERIAL_LEN]; -        uint8_t pad[20 - DB_SERIAL_LEN]; -    }; - -private: // members -    mboard_eeprom_t                         _mb_eeprom; -    dboard_eeprom_t                         _db_eeprom; -    i2c::sptr                               _i2c; - -    boost::mutex    _mutex; -}; - -}}} //namespace - -#endif // INCLUDED_E300_EEPROM_MANAGER_HPP diff --git a/host/lib/usrp/e300/e300_fifo_config.cpp b/host/lib/usrp/e300/e300_fifo_config.cpp deleted file mode 100644 index e34b56ed4..000000000 --- a/host/lib/usrp/e300/e300_fifo_config.cpp +++ /dev/null @@ -1,437 +0,0 @@ -// -// Copyright 2013-2017 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef E300_NATIVE - -#include <uhdlib/utils/system_time.hpp> -#include <uhd/config.hpp> -#include <stdint.h> -#include <atomic> -#include <chrono> -#include <thread> - -// constants coded into the fpga parameters -static const size_t ZF_CONFIG_BASE    = 0x40000000; -static const size_t ZF_PAGE_WIDTH     = 10; -static const size_t H2S_STREAMS_WIDTH = 4; -static const size_t H2S_CMDFIFO_DEPTH = 5; -static const size_t S2H_STREAMS_WIDTH = 4; -static const size_t S2H_CMDFIFO_DEPTH = 5; - -// calculate more useful constants for this module -static const size_t ZF_PAGE_SIZE(1 << ZF_PAGE_WIDTH); -static const size_t H2S_NUM_STREAMS(1 << H2S_STREAMS_WIDTH); -static const size_t H2S_NUM_CMDS(1 << H2S_CMDFIFO_DEPTH); -static const size_t S2H_NUM_STREAMS(1 << S2H_STREAMS_WIDTH); -static const size_t S2H_NUM_CMDS(1 << S2H_CMDFIFO_DEPTH); - -//offsetsinto the arbiter memory map -static const size_t ARBITER_WR_CLEAR      = 0; -static const size_t ARBITER_RD_SIG        = 0; -static const size_t ARBITER_WR_ADDR       = 4; -static const size_t ARBITER_WR_SIZE       = 8; -static const size_t ARBITER_WR_STS_RDY    = 12; -static const size_t ARBITER_WR_STS        = 16; -static const size_t ARBITER_RB_STATUS     = 16; -static const size_t ARBITER_RB_STATUS_OCC = 20; -static const size_t ARBITER_RB_ADDR_SPACE = 24; -static const size_t ARBITER_RB_SIZE_SPACE = 28; - -// registers for the wb32_iface -static const size_t SR_CORE_READBACK = 0; - - -static UHD_INLINE size_t S2H_BASE(const size_t base) -{ -    return base + ZF_PAGE_SIZE * 0; -} - -static UHD_INLINE size_t H2S_BASE(const size_t base) -{ -    return base + ZF_PAGE_SIZE * 1; -} - -static UHD_INLINE size_t REG_BASE(const size_t base) -{ -    return base + ZF_PAGE_SIZE * 2; -} - -static UHD_INLINE size_t DST_BASE(const size_t base) -{ -    return base + ZF_PAGE_SIZE * 3; -} - -static UHD_INLINE size_t ZF_STREAM_OFF(const size_t which) -{ -    return which * 32; -} - -#include "e300_fifo_config.hpp" -#include <sys/mman.h> //mmap -#include <fcntl.h> //open, close -#include <poll.h> //poll -#include <uhd/utils/log.hpp> - -#include <boost/format.hpp> -#include <boost/thread/thread.hpp> //sleep -#include <uhd/types/time_spec.hpp> //timeout -#include <uhd/utils/log.hpp> -#include <uhdlib/utils/atomic.hpp> - -//locking stuff for shared irq -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> - -struct e300_fifo_poll_waiter -{ -    e300_fifo_poll_waiter(const int fd): -        _fd(fd), -        _poll_claimed(false) -    { -        //NOP -    } - -    /*! -     * Waits until the file descriptor fd has data to read. -     * Access to the file descriptor is thread safe. -     */ -    void wait(const double timeout) -    { -        if (timeout == 0) { -            return; -        } - -        boost::mutex::scoped_lock l(_mutex); -        if (_poll_claimed) -        { -            _cond.timed_wait(l, boost::posix_time::microseconds(long(timeout*1000000))); -        } -        else -        { -            _poll_claimed = true; -            l.unlock(); -            struct pollfd fds[1]; -            fds[0].fd = _fd; -            fds[0].events = POLLIN; -            ::poll(fds, 1, long(timeout*1000)); -            if (fds[0].revents & POLLIN) -                ::read(_fd, NULL, 0); - -            l.lock(); -            _poll_claimed = 0; -            _cond.notify_all(); -        } -    } - -    boost::condition_variable _cond; -    boost::mutex _mutex; -    int _fd; -    bool _poll_claimed; -}; - -static const size_t DEFAULT_FRAME_SIZE = 2048; -static const size_t DEFAULT_NUM_FRAMES = 32; - -using namespace uhd; -using namespace uhd::transport; - -struct __mem_addrz_t -{ -    size_t which, phys, data, ctrl; -}; - -/*********************************************************************** - * peek n' poke mmapped space - **********************************************************************/ -UHD_INLINE void zf_poke32(const uint32_t addr, const uint32_t data) -{ -    volatile uint32_t *p = reinterpret_cast<uint32_t *>(addr); -    *p = data; -} - -UHD_INLINE uint32_t zf_peek32(const uint32_t addr) -{ -    volatile const uint32_t *p = reinterpret_cast<const uint32_t *>(addr); -    return *p; -} - -/*********************************************************************** - * managed buffer - **********************************************************************/ -struct e300_fifo_mb : managed_buffer -{ -    e300_fifo_mb(const __mem_addrz_t &addrs, const size_t len): -        ctrl_base(addrs.ctrl), phys_mem(addrs.phys), mem((void *)addrs.data), len(len){} - -    void release(void) -    { -        UHD_ASSERT_THROW(zf_peek32(ctrl_base+ARBITER_RB_ADDR_SPACE) > 0); -        UHD_ASSERT_THROW(zf_peek32(ctrl_base+ARBITER_RB_SIZE_SPACE) > 0); -        zf_poke32(ctrl_base + ARBITER_WR_ADDR, phys_mem); -        zf_poke32(ctrl_base + ARBITER_WR_SIZE, this->size()); -    } - -    template <typename T> -    UHD_INLINE typename T::sptr get_new(void) -    { -        return make(reinterpret_cast<T *>(this), mem, len); -    } - -    const size_t ctrl_base; -    const size_t phys_mem; -    void *const mem; -    const size_t len; -}; - -/*********************************************************************** - * transport - **********************************************************************/ -class e300_transport : public zero_copy_if -{ -public: -    e300_transport( -        boost::shared_ptr<void> allocator, -        const __mem_addrz_t &addrs, -        const size_t num_frames, -        const size_t frame_size, -        e300_fifo_poll_waiter *waiter, -        const bool auto_release -    ): -        _allocator(allocator), -        _addrs(addrs), -        _num_frames(num_frames), -        _frame_size(frame_size), -        _index(0), -        _waiter(waiter) -    { -        //UHD_LOGGER_INFO("E300") << boost::format("phys 0x%x") % addrs.phys ; -        //UHD_LOGGER_INFO("E300") << boost::format("data 0x%x") % addrs.data ; -        //UHD_LOGGER_INFO("E300") << boost::format("ctrl 0x%x") % addrs.ctrl ; - -        const uint32_t sig = zf_peek32(_addrs.ctrl + ARBITER_RD_SIG); -        UHD_ASSERT_THROW((sig >> 16) == 0xACE0); - -        zf_poke32(_addrs.ctrl + ARBITER_WR_CLEAR, 1); -        for (size_t i = 0; i < num_frames; i++) -        { -            //create a managed buffer at the given offset -            __mem_addrz_t mb_addrs = addrs; -            mb_addrs.phys += (i*frame_size); -            mb_addrs.data += (i*frame_size); -            boost::shared_ptr<e300_fifo_mb> mb(new e300_fifo_mb(mb_addrs, frame_size)); - -            //setup the buffers so they are "positioned for use" -            const size_t sts_good = (1 << 7) | (_addrs.which & 0xf); -            if (auto_release) mb->get_new<managed_recv_buffer>(); //release for read -            else zf_poke32(_addrs.ctrl + ARBITER_WR_STS, sts_good); //poke an ok into the sts fifo - -            _buffs.push_back(mb); -        } -    } - -    ~e300_transport(void) -    { -        //NOP -    } - -    template <typename T> -    UHD_INLINE typename T::sptr get_buff(const double timeout) -    { -        const time_spec_t exit_time = uhd::get_system_time() + time_spec_t(timeout); -        while (1) -        { -            if (zf_peek32(_addrs.ctrl + ARBITER_RB_STATUS_OCC)) -            { -                const uint32_t sts = zf_peek32(_addrs.ctrl + ARBITER_RB_STATUS); -                UHD_ASSERT_THROW((sts >> 7) & 0x1); //assert OK -                UHD_ASSERT_THROW((sts & 0xf) == _addrs.which); //expected tag -                zf_poke32(_addrs.ctrl + ARBITER_WR_STS_RDY, 1); //pop from sts fifo -                if (_index == _num_frames) -                    _index = 0; -                return _buffs[_index++]->get_new<T>(); -            } -            if (uhd::get_system_time() > exit_time) { -                break; -            } -            _waiter->wait(timeout); -            //std::this_thread::sleep_for(std::chrono::milliseconds(1)); -        } - -        return typename T::sptr(); -    } - -    managed_recv_buffer::sptr get_recv_buff(const double timeout) -    { -        return this->get_buff<managed_recv_buffer>(timeout); -    } - -    size_t get_num_recv_frames(void) const -    { -        return _num_frames; -    } - -    size_t get_recv_frame_size(void) const -    { -        return _frame_size; -    } - -    managed_send_buffer::sptr get_send_buff(const double timeout) -    { -        return this->get_buff<managed_send_buffer>(timeout); -    } - -    size_t get_num_send_frames(void) const -    { -        return _num_frames; -    } - -    size_t get_send_frame_size(void) const -    { -        return _frame_size; -    } - -private: -    boost::shared_ptr<void> _allocator; -    const __mem_addrz_t _addrs; -    const size_t _num_frames; -    const size_t _frame_size; -    size_t _index; -    e300_fifo_poll_waiter *_waiter; -    std::vector<boost::shared_ptr<e300_fifo_mb> > _buffs; -}; - -/*********************************************************************** - * memory mapping - **********************************************************************/ -class e300_fifo_interface_impl : public virtual e300_fifo_interface -{ -public: -    e300_fifo_interface_impl(const e300_fifo_config_t &config): -        _config(config), -        _bytes_in_use(0), -        _recv_entries_in_use(std::vector<size_t>(S2H_NUM_STREAMS, 0)), -        _send_entries_in_use(std::vector<size_t>(H2S_NUM_STREAMS, 0)) -    { -        //open the file descriptor to our kernel module -        const std::string dev = "/dev/axi_fpga"; -        _fd = ::open(dev.c_str(), O_RDWR|O_SYNC); -        if (_fd < 0) -        { -            throw uhd::runtime_error("e300: failed to open " + dev); -        } - -        //mmap the control and data regions into virtual space -        //UHD_VAR(_config.ctrl_length); -        //UHD_VAR(_config.buff_length); -        //UHD_VAR(_config.phys_addr); -        _buff = ::mmap(NULL, _config.ctrl_length + _config.buff_length, PROT_READ|PROT_WRITE, MAP_SHARED, _fd, 0); -        if (_buff == MAP_FAILED) -        { -            ::close(_fd); -            throw uhd::runtime_error("e300: failed to mmap " + dev); -        } - -        //segment the memory according to zynq fifo arbiter -        _ctrl_space = size_t(_buff); -        _data_space = size_t(_buff) + _config.ctrl_length; - -        //zero out the data region -        std::memset((void *)_data_space, 0, _config.buff_length); - -        //create a poll _waiter for the transports -        _waiter = new e300_fifo_poll_waiter(_fd); -    } - -    virtual ~e300_fifo_interface_impl(void) -    { -        delete _waiter; -        UHD_LOGGER_TRACE("E300")<< "cleanup: munmap" ; -        ::munmap(_buff, _config.ctrl_length + _config.buff_length); -        ::close(_fd); -    } - -    uhd::transport::zero_copy_if::sptr make_recv_xport( -        const size_t which_stream, -        const uhd::transport::zero_copy_xport_params ¶ms) -    { -        return this->_make_xport(which_stream, params, true); -    } - -    uhd::transport::zero_copy_if::sptr make_send_xport( -        const size_t which_stream, -        const uhd::transport::zero_copy_xport_params ¶ms) -    { -        return this->_make_xport(which_stream, params, false); -    } - -    size_t get_global_regs_base() const -    { -        return REG_BASE(_ctrl_space); -    } - -private: -    uhd::transport::zero_copy_if::sptr _make_xport( -        const size_t which_stream, -        const uhd::transport::zero_copy_xport_params ¶ms, -        const bool is_recv) -    { -        boost::mutex::scoped_lock lock(_setup_mutex); - -        const size_t frame_size = is_recv ? params.recv_frame_size : params.send_frame_size; -        const size_t num_frames = is_recv ? params.num_recv_frames : params.num_send_frames; -        size_t &entries_in_use = (is_recv)? _recv_entries_in_use.at(which_stream) -                                          : _send_entries_in_use.at(which_stream); - -        __mem_addrz_t addrs; -        addrs.which = which_stream; -        addrs.phys = _config.phys_addr + _bytes_in_use; -        addrs.data = _data_space + _bytes_in_use; -        addrs.ctrl = ((is_recv)? S2H_BASE(_ctrl_space) : H2S_BASE(_ctrl_space)) + ZF_STREAM_OFF(which_stream); - -        uhd::transport::zero_copy_if::sptr xport; -        if (is_recv) xport.reset(new e300_transport(shared_from_this(), addrs, num_frames, frame_size, _waiter, is_recv)); -        else         xport.reset(new e300_transport(shared_from_this(), addrs, num_frames, frame_size, _waiter, is_recv)); - -        _bytes_in_use += num_frames*frame_size; -        entries_in_use += num_frames; - -        UHD_ASSERT_THROW(_recv_entries_in_use.at(which_stream) <= S2H_NUM_CMDS); -        UHD_ASSERT_THROW(_send_entries_in_use.at(which_stream) <= H2S_NUM_CMDS); -        UHD_ASSERT_THROW(_bytes_in_use <= _config.buff_length); - - -        return xport; -    } - -    e300_fifo_config_t     _config; -    e300_fifo_poll_waiter *_waiter; -    size_t                 _bytes_in_use; -    int                    _fd; -    void                  *_buff; -    size_t                 _ctrl_space; -    size_t                 _data_space; -    std::vector<size_t>    _recv_entries_in_use; -    std::vector<size_t>    _send_entries_in_use; -    boost::mutex           _setup_mutex; -}; - -e300_fifo_interface::sptr e300_fifo_interface::make(const e300_fifo_config_t &config) -{ -    return e300_fifo_interface::sptr(new e300_fifo_interface_impl(config)); -} - -#else //E300_NATIVE - -#include "e300_fifo_config.hpp" -#include <uhd/exception.hpp> - -e300_fifo_interface::sptr e300_fifo_interface::make(const e300_fifo_config_t &) -{ -    throw uhd::assertion_error("e300_fifo_interface::make() !E300_NATIVE"); -} - -#endif //E300_NATIVE diff --git a/host/lib/usrp/e300/e300_fifo_config.hpp b/host/lib/usrp/e300/e300_fifo_config.hpp deleted file mode 100644 index fa6b00eec..000000000 --- a/host/lib/usrp/e300/e300_fifo_config.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_FIFO_CONFIG_HPP -#define INCLUDED_E300_FIFO_CONFIG_HPP - -#include <uhd/types/device_addr.hpp> -#include <uhd/types/wb_iface.hpp> -#include <uhd/transport/zero_copy.hpp> -#include <boost/enable_shared_from_this.hpp> - -struct e300_fifo_config_t -{ -    size_t ctrl_length; -    size_t buff_length; -    size_t phys_addr; -}; - -e300_fifo_config_t e300_read_sysfs(void); -std::string e300_get_sysfs_attr(const std::string &node, const std::string &attr); - -struct e300_fifo_interface : boost::enable_shared_from_this<e300_fifo_interface> -{ -    typedef boost::shared_ptr<e300_fifo_interface> sptr; -    static sptr make(const e300_fifo_config_t &config); - -    virtual uhd::transport::zero_copy_if::sptr make_recv_xport( -        const size_t which_stream, -        const uhd::transport::zero_copy_xport_params ¶ms) = 0; - -    virtual uhd::transport::zero_copy_if::sptr make_send_xport( -        const size_t which_stream, -        const uhd::transport::zero_copy_xport_params &parms) = 0; - -    virtual size_t get_global_regs_base(void) const = 0; -}; - -#endif /* INCLUDED_E300_FIFO_CONFIG_HPP */ diff --git a/host/lib/usrp/e300/e300_fpga_defs.hpp b/host/lib/usrp/e300/e300_fpga_defs.hpp deleted file mode 100644 index 517aa4653..000000000 --- a/host/lib/usrp/e300/e300_fpga_defs.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_FPGA_DEFS_HPP -#define INCLUDED_E300_FPGA_DEFS_HPP -namespace uhd { namespace usrp { namespace e300 { namespace fpga { - -static const size_t NUM_RADIOS = 2; - -static const uint32_t COMPAT_MAJOR = 255; -static const uint32_t COMPAT_MINOR = 0; - -}}}} // namespace - -#endif // INCLUDED_E300_FPGA_DEFS_HPP diff --git a/host/lib/usrp/e300/e300_global_regs.cpp b/host/lib/usrp/e300/e300_global_regs.cpp deleted file mode 100644 index ef607797a..000000000 --- a/host/lib/usrp/e300/e300_global_regs.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_global_regs.hpp" - -#include <stdint.h> -#include <uhd/exception.hpp> -#include <uhd/utils/byteswap.hpp> -#include <cstring> -#include <iostream> - -namespace uhd { namespace usrp { namespace e300 { - -class global_regs_local_impl : public global_regs -{ -public: -    global_regs_local_impl(const size_t ctrl_base) : _ctrl_base(ctrl_base) -    { -    } - -    virtual ~global_regs_local_impl(void) -    { -    } - -    uint32_t peek32(const uhd::wb_iface::wb_addr_type addr) -    { -        // setup readback register -        _poke32(_ctrl_base + global_regs::SR_CORE_READBACK, addr); -        return _peek32(_ctrl_base); -    } - -    void poke32(const uhd::wb_iface::wb_addr_type addr, const uint32_t data) -    { -        _poke32(_ctrl_base + static_cast<size_t>(addr), data); -    } - - -private: -    const size_t _ctrl_base; - -    UHD_INLINE void _poke32(const uint32_t addr, const uint32_t data) -    { -        volatile uint32_t *p = reinterpret_cast<uint32_t *>(addr); -        *p = data; -    } - -    UHD_INLINE uint32_t _peek32(const uint32_t addr) -    { -        volatile const uint32_t *p = reinterpret_cast<const uint32_t *>(addr); -        return *p; -    } -}; - -global_regs::sptr global_regs::make(const size_t ctrl_base) -{ -    return sptr(new global_regs_local_impl(ctrl_base)); -} - -class global_regs_zc_impl : public global_regs -{ -public: -    global_regs_zc_impl(uhd::transport::zero_copy_if::sptr xport) : _xport(xport) -    { -    } - -    virtual ~global_regs_zc_impl(void) -    { -    } - -    uint32_t peek32(const uhd::wb_iface::wb_addr_type addr) -    { -        global_regs_transaction_t transaction; -        transaction.is_poke = uhd::htonx<uint32_t>(0); -        transaction.addr    = uhd::htonx<uint32_t>( -            static_cast<uint32_t>(addr)); -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("global_regs_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("global_regs_zc_impl recv timeout"); -            std::memcpy(&transaction, buff->cast<const void *>(), sizeof(transaction)); -        } -        return uhd::ntohx<uint32_t>(transaction.data); -    } - -    void poke32(const uhd::wb_iface::wb_addr_type addr, const uint32_t data) -    { -        global_regs_transaction_t transaction; -        transaction.is_poke = uhd::htonx<uint32_t>(1); -        transaction.addr    = uhd::htonx<uint32_t>( -            static_cast<uint32_t>(addr)); -        transaction.data    = uhd::htonx<uint32_t>(data); -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw uhd::runtime_error("global_regs_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -    } - -private: -    uhd::transport::zero_copy_if::sptr _xport; -}; - -global_regs::sptr global_regs::make(uhd::transport::zero_copy_if::sptr xport) -{ -    return sptr(new global_regs_zc_impl(xport)); -} - -}}}; diff --git a/host/lib/usrp/e300/e300_global_regs.hpp b/host/lib/usrp/e300/e300_global_regs.hpp deleted file mode 100644 index e7d668d78..000000000 --- a/host/lib/usrp/e300/e300_global_regs.hpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_GLOBAL_REGS_HPP -#define INCLUDED_E300_GLOBAL_REGS_HPP - -#include <uhd/types/wb_iface.hpp> -#include <uhd/transport/zero_copy.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -struct global_regs_transaction_t { -    global_regs_transaction_t(): is_poke(0), addr(0), data(0), pad(0) {} -    uint32_t is_poke; -    uint32_t addr; -    uint32_t data; -    uint32_t pad; -}; - -class global_regs : uhd::noncopyable, public virtual uhd::wb_iface -{ -public: -    typedef boost::shared_ptr<global_regs> sptr; - -    static sptr make(const size_t ctrl_base); -    static sptr make(uhd::transport::zero_copy_if::sptr xport); - -    static const size_t SR_CORE_READBACK = 0; -    static const size_t SR_CORE_MISC     = 4; -    static const size_t SR_CORE_TEST     = 28; -    static const size_t SR_CORE_XB_LOCAL = 32; -    static const size_t SR_CORE_SPI_SEL  = 64; - -    // leave some room for registers, -    // xbar starts with an offset of one -    // 1K page. A part of which is used for -    // DST_LOOKUP for DST_LOOKUP - -    static const size_t SR_CORE_DST       = 1024; -    static const size_t SR_CORE_XBAR      = 2048; - -    static const size_t RB32_CORE_MISC    = 1; -    static const size_t RB32_CORE_COMPAT  = 2; -    static const size_t RB32_CORE_GITHASH = 3; -    static const size_t RB32_CORE_PLL     = 4; -    static const size_t RB32_CORE_NUM_CE  = 8; -    static const size_t RB32_CORE_TEST    = 24; - -    // PPS selection -    static const size_t PPS_GPS = 0; -    static const size_t PPS_INT = 2; -    static const size_t PPS_EXT = 3; -}; - -UHD_INLINE uint32_t XB_ADDR(const uint32_t addr) -{ -    return global_regs::SR_CORE_XBAR + (addr << 2); -} - -UHD_INLINE uint32_t DST_ADDR(const uint32_t addr) -{ -    return global_regs::SR_CORE_DST + (addr << 2); -} - -}}}; - -#endif /* INCLUDED_E300_GLOBAL_REGS_HPP */ diff --git a/host/lib/usrp/e300/e300_i2c.cpp b/host/lib/usrp/e300/e300_i2c.cpp deleted file mode 100644 index 24fd429b5..000000000 --- a/host/lib/usrp/e300/e300_i2c.cpp +++ /dev/null @@ -1,400 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_i2c.hpp" -#include <uhd/exception.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/transport/udp_simple.hpp> - -#include <cstring> -#include <chrono> -#include <thread> - -namespace uhd { namespace usrp { namespace e300 { - -class zc_impl : public i2c -{ -public: -    zc_impl(uhd::transport::zero_copy_if::sptr xport) : _xport(xport) -    { -    } - -    virtual ~zc_impl(void) -    { -    } - -    void set_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg, -        const uint8_t value) -    { -        i2c_transaction_t transaction; -        transaction.type = WRITE | ONEBYTE; -        transaction.addr = addr; -        transaction.reg  = uhd::htonx<uint16_t>(reg); -        transaction.data = value; -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw uhd::runtime_error("i2c_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -    } - -    uint8_t get_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg) -    { -        i2c_transaction_t transaction; -        transaction.type = READ | ONEBYTE; -        transaction.addr = addr; -        transaction.reg = uhd::htonx<uint16_t>(reg); -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("i2c_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("i2c_zc_impl recv timeout"); -            std::memcpy(&transaction, buff->cast<const void *>(), sizeof(transaction)); -        } -        return transaction.data; -    } - -    void set_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg, -        const uint8_t value) -    { -        i2c_transaction_t transaction; -        transaction.type = WRITE | TWOBYTE; -        transaction.addr = addr; -        transaction.reg  = uhd::htonx<uint16_t>(reg); -        transaction.data = value; -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw uhd::runtime_error("i2c_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -    } - -    uint8_t get_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg) -    { -        i2c_transaction_t transaction; -        transaction.type = READ | TWOBYTE; -        transaction.addr = addr; -        transaction.reg  = uhd::htonx<uint16_t>(reg); -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("i2c_zc_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &transaction, sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); -            if (not buff or buff->size() < sizeof(transaction)) -                throw std::runtime_error("i2c_zc_impl recv timeout"); -            std::memcpy(&transaction, buff->cast<const void *>(), sizeof(transaction)); -        } -        return transaction.data; -    } - - -private: -    uhd::transport::zero_copy_if::sptr _xport; -}; - -i2c::sptr i2c::make_zc(uhd::transport::zero_copy_if::sptr xport) -{ -    return sptr(new zc_impl(xport)); -} - -class simple_udp_impl : public i2c -{ -public: -    simple_udp_impl(const std::string &ip_addr, const std::string &port) -    { -        _xport = uhd::transport::udp_simple::make_connected(ip_addr, port); -    } - -    virtual ~simple_udp_impl(void) -    { -    } - -    void set_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg, -        const uint8_t value) -    { -        i2c_transaction_t transaction; -        transaction.type = i2c::WRITE | ONEBYTE; -        transaction.addr = addr; -        transaction.reg  = uhd::htonx<uint16_t>(reg); -        transaction.data = value; - -        _xport->send( -            boost::asio::buffer( -                &transaction, -                sizeof(transaction))); -    } - -    uint8_t get_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg) -    { -        i2c_transaction_t transaction; -        transaction.type = i2c::READ | ONEBYTE; -        transaction.addr = addr; -        transaction.reg  = uhd::htonx<uint16_t>(reg); -        transaction.data = 0; - -        _xport->send( -            boost::asio::buffer( -                &transaction, -                sizeof(transaction))); - -        uint8_t buff[sizeof(i2c_transaction_t)] = {}; -        const size_t nbytes = _xport->recv( -            boost::asio::buffer(buff), 0.100); -        if (not (nbytes == sizeof(transaction))) -            throw std::runtime_error("i2c_simple_udp_impl recv timeout"); -        i2c_transaction_t *reply = reinterpret_cast<i2c_transaction_t*>(buff); -        return reply->data; -    } - -    void set_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg, -        const uint8_t value) -    { -        i2c_transaction_t transaction; -        transaction.type = i2c::WRITE | TWOBYTE; -        transaction.addr = addr; -        transaction.reg = uhd::htonx<uint16_t>(reg); -        transaction.data = value; - -        _xport->send( -            boost::asio::buffer( -                &transaction, -                sizeof(transaction))); -    } - -    uint8_t get_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg) -    { -        i2c_transaction_t transaction; -        transaction.type = i2c::READ | TWOBYTE; -        transaction.addr = addr; -        transaction.reg = uhd::htonx<uint16_t>(reg); -        transaction.data = 0; - -        _xport->send( -            boost::asio::buffer( -                &transaction, -                sizeof(transaction))); - -        uint8_t buff[sizeof(i2c_transaction_t)] = {}; -        const size_t nbytes = _xport->recv( -            boost::asio::buffer(buff), 0.100); -        if (not (nbytes == sizeof(transaction))) -            throw std::runtime_error("i2c_simple_udp_impl recv timeout"); -        i2c_transaction_t *reply = reinterpret_cast<i2c_transaction_t*>(buff); -        return reply->data; -    } - -private: -    uhd::transport::udp_simple::sptr _xport; -}; - -i2c::sptr i2c::make_simple_udp( -    const std::string &ip_addr, -    const std::string &port) -{ -    return sptr(new simple_udp_impl(ip_addr,port)); -} - -}}} // namespace - -#ifdef E300_NATIVE - -#include <linux/i2c.h> -#include <linux/i2c-dev.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/ioctl.h> - -#include <boost/thread.hpp> -#include <stdint.h> - -namespace uhd { namespace usrp { namespace e300 { - -class i2cdev_impl : public i2c -{ -public: -    i2cdev_impl(const std::string &device) -    { -        _fd = ::open(device.c_str(), O_RDWR); -        if (_fd < 0) -            throw uhd::system_error("open failed."); -    } - -    virtual ~i2cdev_impl(void) -    { -        close(_fd); -    } - -    void set_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg, -        const uint8_t value) -    { -        uint8_t outbuf[2]; -        i2c_rdwr_ioctl_data packets; -        i2c_msg messages[1]; - -        messages[0].addr = addr; -        messages[0].flags = 0; -        messages[0].len = sizeof(outbuf); -        messages[0].buf = outbuf; - -        outbuf[0] = reg; -        outbuf[1] = value; - -        packets.msgs = messages; -        packets.nmsgs = 1; - -        if(::ioctl(_fd, I2C_RDWR, &packets) < 0) { -            throw std::runtime_error("ioctl failed"); -        } -        // this is ugly -        std::this_thread::sleep_for(std::chrono::milliseconds(5)); -    } - -    uint8_t get_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg) -    { -        i2c_rdwr_ioctl_data packets; -        i2c_msg messages[2]; - -        uint8_t outbuf = reg; -        messages[0].addr = addr; -        messages[0].flags = 0; -        messages[0].len = sizeof(outbuf); -        messages[0].buf = &outbuf; - -        uint8_t inbuf; -        messages[1].addr = addr; -        messages[1].flags = I2C_M_RD; -        messages[1].len = sizeof(inbuf); -        messages[1].buf = &inbuf; - -        packets.msgs = messages; -        packets.nmsgs = 2; - -        if(::ioctl(_fd, I2C_RDWR, &packets) < 0) { -            throw std::runtime_error("ioctl failed."); -        } - -        return inbuf; -    } - -    // the daughterboard uses 16 bit addresses -    void set_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg, -        const uint8_t value) -    { -        uint8_t outbuf[3]; -        i2c_rdwr_ioctl_data packets; -        i2c_msg messages[1]; - -        messages[0].addr = addr; -        messages[0].flags = 0; -        messages[0].len = sizeof(outbuf); -        messages[0].buf = outbuf; - -        outbuf[0] = (reg >> 8) & 0xff; -        outbuf[1] = reg & 0xff; -        outbuf[2] = value; - -        packets.msgs = messages; -        packets.nmsgs = 1; - -        if(::ioctl(_fd, I2C_RDWR, &packets) < 0) { -            throw std::runtime_error("ioctl failed"); -        } -        // this is ugly -        std::this_thread::sleep_for(std::chrono::milliseconds(5)); -    } - - -    // the daughterboard eeprom uses 16 bit addresses -    uint8_t get_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg) -    { -        i2c_rdwr_ioctl_data packets; -        i2c_msg messages[2]; - -        // always little endian -        uint8_t outbuf[2]; -        outbuf[0] = (reg >> 8) & 0xff; -        outbuf[1] = reg & 0xff; - -        messages[0].addr = addr; -        messages[0].flags = 0; -        messages[0].len = sizeof(outbuf); -        messages[0].buf = outbuf; - -        uint8_t inbuf; -        messages[1].addr = addr; -        messages[1].flags = I2C_M_RD; -        messages[1].len = sizeof(inbuf); -        messages[1].buf = &inbuf; - -        packets.msgs = messages; -        packets.nmsgs = 2; - -        if(::ioctl(_fd, I2C_RDWR, &packets) < 0) { -            throw std::runtime_error("ioctl failed."); -        } - -        return inbuf; -    } - -private: -    int _fd; -}; - -}}} // namespace - -using namespace uhd::usrp::e300; - -i2c::sptr i2c::make_i2cdev(const std::string &device) -{ -    return sptr(new i2cdev_impl(device)); -} -#else -using namespace uhd::usrp::e300; - -i2c::sptr i2c::make_i2cdev(const std::string &) -{ -    throw uhd::assertion_error("i2c::make() !E300_NATIVE"); -} -#endif // E300_NATIVE diff --git a/host/lib/usrp/e300/e300_i2c.hpp b/host/lib/usrp/e300/e300_i2c.hpp deleted file mode 100644 index 1606d2146..000000000 --- a/host/lib/usrp/e300/e300_i2c.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_I2C_HPP -#define INCLUDED_E300_I2C_HPP - -#include <uhd/utils/noncopyable.hpp> -#include <stdint.h> -#include <boost/shared_ptr.hpp> - -#include <uhd/transport/zero_copy.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -struct i2c_transaction_t { -    i2c_transaction_t(): reg(0), addr(0), data(0), type(0) {}; -    uint16_t reg; -    uint8_t  addr; -    uint8_t  data; -    uint8_t  type; -}; - -class i2c : public uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<i2c> sptr; - -    static sptr make_i2cdev(const std::string &device); -    static sptr make_zc(uhd::transport::zero_copy_if::sptr xport); -    static sptr make_simple_udp( -        const std::string &ip_addr, -        const std::string &port); - -    virtual uint8_t get_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg) = 0; - -    virtual uint8_t get_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg) = 0; - -    virtual void set_i2c_reg8( -        const uint8_t addr, -        const uint8_t reg, -        const uint8_t value) = 0; - -    virtual void set_i2c_reg16( -        const uint8_t addr, -        const uint16_t reg, -        const uint8_t value) = 0; - - -    static const uint8_t DB_EEPROM_ADDR = 0x50; -    static const uint8_t MB_EEPROM_ADDR = 0x51; - -    static const uint8_t WRITE          = 0x1; -    static const uint8_t READ           = 0x0; -    static const uint8_t TWOBYTE        = 0x4; -    static const uint8_t ONEBYTE        = 0x2; -}; - -}}}; - -#endif // INCLUDED_E300_I2C_HPP diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp deleted file mode 100644 index 59a8cec88..000000000 --- a/host/lib/usrp/e300/e300_impl.cpp +++ /dev/null @@ -1,749 +0,0 @@ -// -// Copyright 2013-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_impl.hpp" -#include "e300_defaults.hpp" -#include "e300_fpga_defs.hpp" -#include "e300_spi.hpp" -#include "e300_regs.hpp" -#include "e300_eeprom_manager.hpp" -#include "e300_sensor_manager.hpp" -#include "e300_common.hpp" -#include "e300_remote_codec_ctrl.hpp" -#include "e3xx_radio_ctrl_impl.hpp" - - -#include <uhd/utils/log.hpp> -#include <uhd/utils/static.hpp> -#include <uhd/utils/paths.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/transport/if_addrs.hpp> -#include <uhd/transport/udp_zero_copy.hpp> -#include <uhd/transport/udp_simple.hpp> -#include <uhd/types/sensors.hpp> -#include <boost/make_shared.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/format.hpp> -#include <boost/filesystem.hpp> -#include <boost/functional/hash.hpp> -#include <boost/bind.hpp> -#include <boost/make_shared.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/thread/thread.hpp> //sleep -#include <boost/asio.hpp> -#include <fstream> - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::usrp::gpio_atr; -using namespace uhd::transport; -namespace fs = boost::filesystem; -namespace asio = boost::asio; - -namespace uhd { namespace usrp { namespace e300 { - -/*********************************************************************** - * Discovery - **********************************************************************/ - -static std::vector<std::string> discover_ip_addrs( -    const std::string& addr_hint, const std::string& port) -{ -    std::vector<std::string> addrs; - -    // Create a UDP transport to communicate: -    // Some devices will cause a throw when opened for a broadcast address. -    // We print and recover so the caller can loop through all bcast addrs. -    uhd::transport::udp_simple::sptr udp_bcast_xport; -    try { -        udp_bcast_xport = uhd::transport::udp_simple::make_broadcast(addr_hint, port); -    } catch(const std::exception &e) { -        UHD_LOGGER_ERROR("E300") << boost::format("Cannot open UDP transport on %s for discovery%s") -        % addr_hint % e.what() ; -        return addrs; -    } catch(...) { -        UHD_LOGGER_ERROR("E300") << "E300 Network discovery unknown error"; -        return addrs; -    } - -    // TODO: Do not abuse the I2C transport here ... -    // we send a read request to i2c address 0x51, -    // to read register 0 -    i2c_transaction_t req; -    req.type = i2c::READ | i2c::ONEBYTE; -    req.addr = 0x51; // mboard's eeprom address, we don't really care -    req.reg = 4; - -    // send dummy request -    try { -    udp_bcast_xport->send(boost::asio::buffer(&req, sizeof(req))); -    } catch (const std::exception &ex) { -        UHD_LOGGER_ERROR("E300") << "E300 Network discovery error " << ex.what(); -        return addrs; -    } catch(...) { -        UHD_LOGGER_ERROR("E300") << "E300 Network discovery unknown error"; -        return addrs; -    } - -    // loop for replies until timeout -    while (true) { -        uint8_t buff[sizeof(i2c_transaction_t)] = {}; -        const size_t nbytes = udp_bcast_xport->recv(boost::asio::buffer(buff), 0.050); -        if (nbytes == 0) -            break; //No more responses - -        const i2c_transaction_t *reply = reinterpret_cast<const i2c_transaction_t*>(buff); -        if (req.addr == reply->addr) -           addrs.push_back(udp_bcast_xport->get_recv_addr()); -    } - -    return addrs; -} - -static bool is_loopback(const if_addrs_t &if_addrs) -{ -       return if_addrs.inet == asio::ip::address_v4::loopback().to_string(); -} - -device_addrs_t e300_find(const device_addr_t &multi_dev_hint) -{ -    // handle multi device discovery -    device_addrs_t hints = separate_device_addr(multi_dev_hint); - -    if (hints.size() > 1) { -        device_addrs_t found_devices; -        std::string err_msg; -        BOOST_FOREACH(const device_addr_t &hint_i, hints) -        { -            device_addrs_t found_devices_i = e300_find(hint_i); -            if(found_devices_i.size() != 1) -                err_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 err_msg.empty()) -                throw uhd::value_error(err_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 e300_addrs; - -    // return an empty list of addresses when type is set to non-e300 -    if (hint.has_key("type") and hint["type"] != "e3x0") -        return e300_addrs; - -    const bool loopback_only = -        get_if_addrs().size() == 1 and is_loopback(get_if_addrs().at(0)); - -    // if we don't have connectivity, we might as well skip the network part -    if (not loopback_only) { -        // if no address or node has been specified, send a broadcast -        if ((not hint.has_key("addr")) and (not hint.has_key("node"))) { -            BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()) -            { -                // avoid the loopback device -                if (is_loopback(if_addrs)) -                    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_e300_addrs = e300_find(new_hint); -                e300_addrs.insert(e300_addrs.begin(), -                    new_e300_addrs.begin(), new_e300_addrs.end()); - -            } -            return e300_addrs; -        } - -        std::vector<std::string> ip_addrs = discover_ip_addrs( -            hint["addr"], E300_SERVER_I2C_PORT); - -        BOOST_FOREACH(const std::string &ip_addr, ip_addrs) -        { -            device_addr_t new_addr; -            new_addr["type"] = "e3x0"; -            new_addr["addr"] = ip_addr; - -            // see if we can read the eeprom -            try { -                e300_eeprom_manager eeprom_manager( -                    i2c::make_simple_udp(new_addr["addr"], E300_SERVER_I2C_PORT)); -                const mboard_eeprom_t eeprom = eeprom_manager.get_mb_eeprom(); -                new_addr["name"] = eeprom["name"]; -                new_addr["serial"] = eeprom["serial"]; -                new_addr["product"] = eeprom_manager.get_mb_type_string(); -            } catch (...) { -                // set these values as empty string, so the device may still be found -                // and the filters 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"])) -            { -                e300_addrs.push_back(new_addr); -            } -        } -    } - -    // finally search locally -    // if device node is not provided, -    // use the default one -    if (not hint.has_key("node")) { -        device_addr_t new_addr = hint; -        new_addr["node"] = "/dev/axi_fpga"; -        return e300_find(new_addr); -    } - -    // use the given node -    if (fs::exists(hint["node"])) { -        device_addr_t new_addr; -        new_addr["type"] = "e3x0"; -        new_addr["node"] = fs::system_complete(fs::path(hint["node"])).string(); - -        try { -            e300_eeprom_manager eeprom_manager(i2c::make_i2cdev(E300_I2CDEV_DEVICE)); -            const mboard_eeprom_t eeprom = eeprom_manager.get_mb_eeprom(); -            new_addr["name"] = eeprom["name"]; -            new_addr["serial"] = eeprom["serial"]; -            new_addr["product"] = eeprom_manager.get_mb_type_string(); -        } catch (...) { -            // set these values as empty string, so the device may still be found -            // and the filters 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"])) -        { -            e300_addrs.push_back(new_addr); -        } -    } - -    return e300_addrs; -} - - -/*********************************************************************** - * Make - **********************************************************************/ -static device::sptr e300_make(const device_addr_t &device_addr) -{ -    UHD_LOGGER_DEBUG("E300")<< "e300_make with args " << device_addr.to_pp_string() ; -    if(device_addr.has_key("server")) -        throw uhd::runtime_error( -            str(boost::format("Please run the server executable \"%s\"") -                % "usrp_e3x0_network_mode")); -    else -        return device::sptr(new e300_impl(device_addr)); -} - -// Common code used by e300_impl and e300_image_loader -void get_e3x0_fpga_images(const uhd::device_addr_t &device_addr, -                          std::string &fpga_image, -                          std::string &idle_image){ -    const uint16_t pid = boost::lexical_cast<uint16_t>( -            device_addr["product"]); - -    //extract the FPGA path for the e300 -    switch(e300_eeprom_manager::get_mb_type(pid)) { -    case e300_eeprom_manager::USRP_E310_SG1_MB: -        fpga_image = device_addr.cast<std::string>("fpga", -            find_image_path(E310_SG1_FPGA_FILE_NAME)); -        idle_image = find_image_path(E3XX_SG1_FPGA_IDLE_FILE_NAME); -        break; -    case e300_eeprom_manager::USRP_E310_SG3_MB: -        fpga_image = device_addr.cast<std::string>("fpga", -            find_image_path(E310_SG3_FPGA_FILE_NAME)); -        idle_image = find_image_path(E3XX_SG3_FPGA_IDLE_FILE_NAME); -        break; -    case e300_eeprom_manager::USRP_E300_MB: -        fpga_image = device_addr.cast<std::string>("fpga", -            find_image_path(E300_FPGA_FILE_NAME)); -        idle_image = find_image_path(E3XX_SG1_FPGA_IDLE_FILE_NAME); -        break; -    case e300_eeprom_manager::UNKNOWN: -    default: -        UHD_LOGGER_WARNING("E300") << "Unknown motherboard type, loading e300 image." -                             ; -        fpga_image = device_addr.cast<std::string>("fpga", -            find_image_path(E300_FPGA_FILE_NAME)); -        idle_image = find_image_path(E3XX_SG1_FPGA_IDLE_FILE_NAME); -        break; -    } -} - -/*********************************************************************** - * Structors - **********************************************************************/ -e300_impl::e300_impl(const uhd::device_addr_t &device_addr) -    : _device_addr(device_addr) -    , _xport_path(device_addr.has_key("addr") ? ETH : AXI) -    , _dma_chans_available(MAX_DMA_CHANNEL_PAIRS, ~size_t(0) /* all available at the beginning */) -{ -    stream_options.rx_fc_request_freq = E300_RX_FC_REQUEST_FREQ; - -    //////////////////////////////////////////////////////////////////// -    // load the fpga image -    //////////////////////////////////////////////////////////////////// -    if (_xport_path == AXI) { -        _do_not_reload = device_addr.has_key("no_reload_fpga"); -        if (not _do_not_reload) { -            std::string fpga_image; - -            // need to re-read product ID code because of conversion into string in find function -            e300_eeprom_manager eeprom_manager(i2c::make_i2cdev(E300_I2CDEV_DEVICE)); -            const mboard_eeprom_t eeprom = eeprom_manager.get_mb_eeprom(); -            device_addr_t device_addr_cp(device_addr.to_string()); -            device_addr_cp["product"] = eeprom["product"]; - -            get_e3x0_fpga_images(device_addr_cp, -                                 fpga_image, -                                 _idle_image); -            common::load_fpga_image(fpga_image); -        } -    } - -    //////////////////////////////////////////////////////////////////// -    // setup fifo xports -    //////////////////////////////////////////////////////////////////// -    _ctrl_xport_params.recv_frame_size = e300::DEFAULT_CTRL_FRAME_SIZE; -    _ctrl_xport_params.num_recv_frames = e300::DEFAULT_CTRL_NUM_FRAMES; -    _ctrl_xport_params.send_frame_size = e300::DEFAULT_CTRL_FRAME_SIZE; -    _ctrl_xport_params.num_send_frames = e300::DEFAULT_CTRL_NUM_FRAMES; - -    _data_xport_params.recv_frame_size = device_addr.cast<size_t>("recv_frame_size", -        e300::DEFAULT_RX_DATA_FRAME_SIZE); -    _data_xport_params.num_recv_frames = device_addr.cast<size_t>("num_recv_frames", -        e300::DEFAULT_RX_DATA_NUM_FRAMES); -    _data_xport_params.send_frame_size = device_addr.cast<size_t>("send_frame_size", -        e300::DEFAULT_TX_DATA_FRAME_SIZE); -    _data_xport_params.num_send_frames = device_addr.cast<size_t>("num_send_frames", -        e300::DEFAULT_TX_DATA_NUM_FRAMES); - - -    // until we figure out why this goes wrong we'll keep this hack around for -    // the ethernet case, in the AXI case we cannot go above one page -    if (_xport_path == ETH) { -        _data_xport_params.recv_frame_size = -            std::min(e300::MAX_NET_RX_DATA_FRAME_SIZE, _data_xport_params.recv_frame_size); -        _data_xport_params.send_frame_size = -            std::min(e300::MAX_NET_TX_DATA_FRAME_SIZE, _data_xport_params.send_frame_size); -    } else { -        _data_xport_params.recv_frame_size = -            std::min(e300::MAX_AXI_RX_DATA_FRAME_SIZE, _data_xport_params.recv_frame_size); -        _data_xport_params.send_frame_size = -            std::min(e300::MAX_AXI_TX_DATA_FRAME_SIZE, _data_xport_params.send_frame_size); -    } -    udp_zero_copy::buff_params dummy_buff_params_out; - -    ad9361_ctrl::sptr  codec_ctrl; -    if (_xport_path == ETH) { -        zero_copy_if::sptr codec_xport = -            udp_zero_copy::make(device_addr["addr"], E300_SERVER_CODEC_PORT, _ctrl_xport_params, dummy_buff_params_out, device_addr); -        codec_ctrl = e300_remote_codec_ctrl::make(codec_xport); -        zero_copy_if::sptr gregs_xport = -            udp_zero_copy::make(device_addr["addr"], E300_SERVER_GREGS_PORT, _ctrl_xport_params, dummy_buff_params_out, device_addr); -        _global_regs = global_regs::make(gregs_xport); - -        zero_copy_if::sptr i2c_xport; -        i2c_xport = udp_zero_copy::make(device_addr["addr"], E300_SERVER_I2C_PORT, _ctrl_xport_params, dummy_buff_params_out, device_addr); -        _eeprom_manager = boost::make_shared<e300_eeprom_manager>(i2c::make_zc(i2c_xport)); - -        uhd::transport::zero_copy_xport_params sensor_xport_params; -        sensor_xport_params.recv_frame_size = 128; -        sensor_xport_params.num_recv_frames = 10; -        sensor_xport_params.send_frame_size = 128; -        sensor_xport_params.num_send_frames = 10; - -        zero_copy_if::sptr sensors_xport; -        sensors_xport = udp_zero_copy::make(device_addr["addr"], E300_SERVER_SENSOR_PORT, sensor_xport_params, dummy_buff_params_out, device_addr); -        _sensor_manager = e300_sensor_manager::make_proxy(sensors_xport); - -    } else { -        e300_fifo_config_t fifo_cfg; -        try { -            fifo_cfg = e300_read_sysfs(); -        } catch (...) { -            throw uhd::runtime_error("Failed to get driver parameters from sysfs."); -        } -        _fifo_iface = e300_fifo_interface::make(fifo_cfg); -        _global_regs = global_regs::make(_fifo_iface->get_global_regs_base()); - -        ad9361_params::sptr client_settings = boost::make_shared<e300_ad9361_client_t>(); -        codec_ctrl = ad9361_ctrl::make_spi(client_settings, spi::make(E300_SPIDEV_DEVICE), 1); -        // This is horrible ... why do I have to sleep here? -        boost::this_thread::sleep(boost::posix_time::milliseconds(100)); -        _eeprom_manager = boost::make_shared<e300_eeprom_manager>(i2c::make_i2cdev(E300_I2CDEV_DEVICE)); -        _sensor_manager = e300_sensor_manager::make_local(_global_regs); -    } - -#ifdef E300_GPSD -    UHD_LOGGER_INFO("E300") << "Detecting internal GPS "; -    try { -        if (_xport_path == AXI) -            _gps = gpsd_iface::make("localhost", 2947); -        else -            _gps = gpsd_iface::make(device_addr["addr"], 2947); -    } catch (std::exception &e) { -        UHD_LOGGER_ERROR("E300") << "An error occured making GPSDd interface: " << e.what(); -    } - -    if (_gps) { -        for (size_t i = 0; i < _GPS_TIMEOUT; i++) -        { -            boost::this_thread::sleep(boost::posix_time::seconds(1)); -            if (!_gps->gps_detected()) -                std::cout << "." << std::flush; -            else { -                std::cout << ".... " << std::flush; -                break; -            } -        } -        UHD_LOGGER_INFO("E300") << "GPSDO " << (_gps->gps_detected() ? "found" : "not found"); -    } -#endif - -    // Verify we can talk to the e300 core control registers ... -    UHD_LOGGER_INFO("E300") << "Initializing core control (global registers)..." << std::endl; -    this->_register_loopback_self_test( -        _global_regs, -        global_regs::SR_CORE_TEST, -        global_regs::RB32_CORE_TEST -    ); - -    // Verify fpga compatibility version matches at least for the major -    if (_get_version(FPGA_MAJOR) != fpga::COMPAT_MAJOR) { -        throw uhd::runtime_error(str(boost::format( -            "Expected FPGA compatibility number %lu.x, but got %lu.%lu:\n" -            "The FPGA build is not compatible with the host code build.\n" -            "%s" -        ) % fpga::COMPAT_MAJOR -          % _get_version(FPGA_MAJOR) % _get_version(FPGA_MINOR) -          % print_utility_error("uhd_images_downloader.py"))); -    } - -    //////////////////////////////////////////////////////////////////// -    // Initialize the properties tree -    //////////////////////////////////////////////////////////////////// -    _tree->create<std::string>("/name").set("E-Series Device"); -    const fs_path mb_path = "/mboards/0"; -    _tree->create<std::string>(mb_path / "name") -        .set(_eeprom_manager->get_mb_type_string()); - -    _tree->create<std::string>(mb_path / "codename").set("Troll"); - -    _tree->create<std::string>(mb_path / "fpga_version").set( -        str(boost::format("%u.%u") -            % _get_version(FPGA_MAJOR) -            % _get_version(FPGA_MINOR))); - -    _tree->create<std::string>(mb_path / "fpga_version_hash").set( -        _get_version_hash()); - -    // Clock reference source -    _tree->create<std::string>(mb_path / "clock_source" / "value") -        .add_coerced_subscriber(boost::bind(&e300_impl::_update_clock_source, this, _1)) -        .set(e300::DEFAULT_CLOCK_SRC); -    static const std::vector<std::string> clock_sources = -        boost::assign::list_of("internal"); //external,gpsdo not supported -    _tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options").set(clock_sources); - -    //////////////////////////////////////////////////////////////////// -    // and do the misc mboard sensors -    //////////////////////////////////////////////////////////////////// -    _tree->create<int>(mb_path / "sensors"); -    BOOST_FOREACH(const std::string &name, _sensor_manager->get_sensors()) -    { -        _tree->create<sensor_value_t>(mb_path / "sensors" / name) -            .set_publisher(boost::bind(&e300_sensor_manager::get_sensor, _sensor_manager, name)); -    } -#ifdef E300_GPSD -    if (_gps) { -        BOOST_FOREACH(const std::string &name, _gps->get_sensors()) -        { -            _tree->create<sensor_value_t>(mb_path / "sensors" / name) -                .set_publisher(boost::bind(&gpsd_iface::get_sensor, _gps, name)); -        } -    } -#endif - -    //////////////////////////////////////////////////////////////////// -    // setup the mboard eeprom -    //////////////////////////////////////////////////////////////////// -    _tree->create<mboard_eeprom_t>(mb_path / "eeprom") -        .set(_eeprom_manager->get_mb_eeprom())  // set first... -        .add_coerced_subscriber(boost::bind( -            &e300_eeprom_manager::write_mb_eeprom, -            _eeprom_manager, _1)); - -    //////////////////////////////////////////////////////////////////// -    // dboard eeproms but not really -    //////////////////////////////////////////////////////////////////// -    dboard_eeprom_t db_eeprom; -    _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "rx_eeprom") -        .set(_eeprom_manager->get_db_eeprom()) -        .add_coerced_subscriber(boost::bind( -            &e300_eeprom_manager::write_db_eeprom, -            _eeprom_manager, _1)); - -    _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "tx_eeprom") -        .set(_eeprom_manager->get_db_eeprom()) -        .add_coerced_subscriber(boost::bind( -            &e300_eeprom_manager::write_db_eeprom, -            _eeprom_manager, _1)); - -    _tree->create<dboard_eeprom_t>(mb_path / "dboards" / "A" / "gdb_eeprom").set(db_eeprom); - -    //////////////////////////////////////////////////////////////////// -    // Access to global regs -    //////////////////////////////////////////////////////////////////// -    _tree->create<uint32_t>(mb_path / "global_regs" / "misc") -        .add_coerced_subscriber(boost::bind(&global_regs::poke32, _global_regs, global_regs::SR_CORE_MISC, _1)) -    ; -    _tree->create<uint32_t>(mb_path / "global_regs" / "pll") -        .set_publisher(boost::bind(&global_regs::peek32, _global_regs, global_regs::RB32_CORE_PLL)) -    ; - -    //////////////////////////////////////////////////////////////////// -    // clocking -    //////////////////////////////////////////////////////////////////// -    _tree->create<double>(mb_path / "tick_rate") -        .add_coerced_subscriber(boost::bind(&device3_impl::update_tx_streamers, this, _1)) -        .add_coerced_subscriber(boost::bind(&device3_impl::update_rx_streamers, this, _1)) -    ; - -    //default some chains on -- needed for setup purposes -    UHD_LOGGER_DEBUG("E300") << "Initializing AD9361 using hard SPI core..." << std::flush; -    codec_ctrl->set_active_chains(true, false, true, false); -    codec_ctrl->set_clock_rate(50e6); -    UHD_LOGGER_DEBUG("E300") << "OK" << std::endl; - -    //////////////////////////////////////////////////////////////////// -    // Set up RFNoC blocks -    //////////////////////////////////////////////////////////////////// -    const size_t n_rfnoc_blocks = _global_regs->peek32(global_regs::RB32_CORE_NUM_CE); -    enumerate_rfnoc_blocks( -        0, /* mboard index */ -        n_rfnoc_blocks, -        E300_XB_DST_AXI + 1, /* base port, rfnoc blocks come after the AXI connect */ -        uhd::sid_t(E300_DEVICE_HERE, 0, E300_DEVICE_THERE, 0), -        device_addr_t() -    ); - -    // If we have a radio, we must configure its codec control: -    std::vector<rfnoc::block_id_t> radio_ids = find_blocks<rfnoc::e3xx_radio_ctrl_impl>("Radio"); -    if (radio_ids.size() > 0) { -        UHD_LOGGER_DEBUG("E300") << "Initializing Radio Block..." << std::endl; -        get_block_ctrl<rfnoc::e3xx_radio_ctrl_impl>(radio_ids[0])->setup_radio(codec_ctrl); -        if (radio_ids.size() != 1) { -            UHD_LOGGER_WARNING("E300") << "Too many Radio Blocks found. Using only " << radio_ids[0] << std::endl; -        } -    } else { -        UHD_LOGGER_DEBUG("E300") << "No Radio Block found. Assuming radio-less operation." << std::endl; -    } - -    //////////////////////////////////////////////////////////////////// -    // do some post-init tasks -    //////////////////////////////////////////////////////////////////// -    // init the clock rate to something reasonable -    _tree->access<double>(mb_path / "tick_rate") -        .set(device_addr.cast<double>("master_clock_rate", ad936x_manager::DEFAULT_TICK_RATE)); - -    // subdev spec contains full width of selections -    subdev_spec_t rx_spec, tx_spec; -    BOOST_FOREACH(const std::string &fe, _tree->list(mb_path / "dboards" / "A" / "rx_frontends")) -    { -        rx_spec.push_back(subdev_spec_pair_t("A", fe)); -    } -    BOOST_FOREACH(const std::string &fe, _tree->list(mb_path / "dboards" / "A" / "tx_frontends")) -    { -        tx_spec.push_back(subdev_spec_pair_t("A", fe)); -    } -    _tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_spec); -    _tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec); -    UHD_LOGGER_DEBUG("E300") << "end of e300_impl()" << std::endl; -} - -e300_impl::~e300_impl(void) -{ -    // Force RFNoC destructors to fire before loading the idle image -    _rfnoc_block_ctrl.clear(); -    if (_xport_path == AXI and not _do_not_reload) -        common::load_fpga_image(_idle_image); -} - -void e300_impl::_register_loopback_self_test(wb_iface::sptr iface, uint32_t w_addr, uint32_t r_addr) -{ -    bool test_fail = false; -    UHD_LOGGER_INFO("E300") << "Performing register loopback test... "; -    size_t hash = size_t(time(NULL)); -    for (size_t i = 0; i < 100; i++) -    { -        boost::hash_combine(hash, i); -        iface->poke32(w_addr, uint32_t(hash)); -        test_fail = iface->peek32(r_addr) != uint32_t(hash); -        if (test_fail) break; //exit loop on any failure -    } -    UHD_LOGGER_INFO("E300") << "Register loopback test " << ((test_fail)? " failed" : "passed"); -} - -uint32_t e300_impl::_get_version(compat_t which) -{ -    const uint16_t compat_num -        = _global_regs->peek32(global_regs::RB32_CORE_COMPAT); - -    switch(which) { -    case FPGA_MINOR: -        return compat_num & 0xff; -    case FPGA_MAJOR: -        return (compat_num & 0xff00) >> 8; -    default: -        throw uhd::value_error("Requested unknown version."); -    }; -} - -std::string e300_impl::_get_version_hash(void) -{ -    const uint32_t git_hash -        = _global_regs->peek32(global_regs::RB32_CORE_GITHASH); -    return str(boost::format("%7x%s") -        % (git_hash & 0x0FFFFFFF) -        % ((git_hash & 0xF0000000) ? "-dirty" : "")); -} - - -void e300_impl::_setup_dest_mapping( -    const uhd::sid_t &sid, -    const size_t which_stream) -{ -    UHD_LOGGER_DEBUG("E300") << boost::format("[E300] Setting up dest map for host ep %lu to be stream %d") -                                     % sid.get_src_endpoint() % which_stream << std::endl; -    _global_regs->poke32(DST_ADDR(sid.get_src_endpoint()), which_stream); -} - -size_t e300_impl::_get_axi_dma_channel_pair() -{ -    if (_dma_chans_available.none()) { -        throw uhd::runtime_error("No more free DMA channels available."); -    } - -    size_t first_free_pair = _dma_chans_available.find_first(); -    _dma_chans_available.reset(first_free_pair); -    return first_free_pair; -} - -uint16_t e300_impl::_get_udp_port( -        uint8_t destination, -        uint8_t prefix) -{ -    if (destination == E300_XB_DST_RADIO) { -        if (prefix == E300_RADIO_DEST_PREFIX_CTRL) -            return boost::lexical_cast<uint16_t>(E300_SERVER_CTRL_PORT0); -        else if (prefix == E300_RADIO_DEST_PREFIX_TX) -            return boost::lexical_cast<uint16_t>(E300_SERVER_TX_PORT0); -        else if (prefix == E300_RADIO_DEST_PREFIX_RX) -            return boost::lexical_cast<uint16_t>(E300_SERVER_RX_PORT0); -    } else if (destination == E300_XB_DST_R1) { -        if (prefix == E300_RADIO_DEST_PREFIX_CTRL) -            return boost::lexical_cast<uint16_t>(E300_SERVER_CTRL_PORT1); -        else if (prefix == E300_RADIO_DEST_PREFIX_TX) -            return boost::lexical_cast<uint16_t>(E300_SERVER_TX_PORT1); -        else if (prefix == E300_RADIO_DEST_PREFIX_RX) -            return boost::lexical_cast<uint16_t>(E300_SERVER_RX_PORT1); -    } -    throw uhd::value_error(str(boost::format("No UDP port defined for combination: %u %u") % destination % prefix)); -} - -uhd::sid_t e300_impl::_allocate_sid( -    const uhd::sid_t &address) -{ -    uhd::sid_t sid = address; -    sid.set_src_addr(E300_DEVICE_HERE); -    sid.set_src_endpoint(_sid_framer); - -    // TODO: We don't have to do this everytime ... -    // Program the E300 to recognize it's own local address. -    _global_regs->poke32(global_regs::SR_CORE_XB_LOCAL, address.get_dst_addr()); - -    // Program CAM entry for outgoing packets matching a E300 resource -    // (e.g. Radio). -    // This type of packet matches the XB_LOCAL address and is looked up in -    // the upper half of the CAM -    _global_regs->poke32(XB_ADDR(256 + address.get_dst_endpoint()), address.get_dst_xbarport()); - -    // TODO: We don't have to do this everytime ... -    // Program CAM entry for returning packets to us -    // (for example host via zynq_fifo) -    // This type of packet does not match the XB_LOCAL address and is -    // looked up in the lower half of the CAM -    _global_regs->poke32(XB_ADDR(E300_DEVICE_HERE), E300_XB_DST_AXI); - -    // increment for next setup -    _sid_framer++; - -    return sid; -} - -uhd::both_xports_t e300_impl::make_transport( -    const uhd::sid_t &address, -    const xport_type_t type, -    const uhd::device_addr_t &) -{ -    uhd::both_xports_t xports; -    xports.endianness = ENDIANNESS_LITTLE; - -    const uhd::transport::zero_copy_xport_params params = -        (type == CTRL) ? _ctrl_xport_params : _data_xport_params; - -    xports.send_sid = _allocate_sid(address); -    xports.recv_sid = xports.send_sid.reversed(); -    xports.recv_buff_size = params.recv_frame_size * params.num_recv_frames; -    xports.send_buff_size = params.send_frame_size * params.num_send_frames; - -    if (_xport_path != AXI) { -        throw uhd::runtime_error("[E300] Currently only AXI transport supported with RFNOC"); -    } - -    const size_t chan_pair = _get_axi_dma_channel_pair(); -    xports.send = _fifo_iface->make_send_xport(chan_pair, params); -    xports.recv = _fifo_iface->make_recv_xport(chan_pair, params); -    _setup_dest_mapping(xports.send_sid, chan_pair); - -    return xports; -} - -void e300_impl::_update_clock_source(const std::string &source) -{ -    if (source != "internal") { -        throw uhd::value_error(boost::str( -            boost::format("Clock source option not supported: %s. The only value supported is \"internal\". " \ -                          "To discipline the internal oscillator, set the appropriate time source.") % source -        )); -    } -} - -}}} // namespace - -UHD_STATIC_BLOCK(register_e300_device) -{ -    device::register_device(&uhd::usrp::e300::e300_find, &uhd::usrp::e300::e300_make, uhd::device::USRP); -} diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp deleted file mode 100644 index 2e919cf9b..000000000 --- a/host/lib/usrp/e300/e300_impl.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// -// Copyright 2013-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_IMPL_HPP -#define INCLUDED_E300_IMPL_HPP - -#include "../device3/device3_impl.hpp" -#include <uhd/property_tree.hpp> -#include <uhd/usrp/mboard_eeprom.hpp> -#include <uhd/usrp/dboard_eeprom.hpp> -#include <uhd/usrp/subdev_spec.hpp> -#include <uhd/types/serial.hpp> -#include <uhd/types/sensors.hpp> - -#include <boost/weak_ptr.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/dynamic_bitset.hpp> -#include <string> -#include "e300_fifo_config.hpp" - -#include "e300_global_regs.hpp" -#include "e300_i2c.hpp" -#include "e300_eeprom_manager.hpp" -#include "e300_sensor_manager.hpp" - -/* if we don't compile with gpsd support, don't bother */ -#ifdef E300_GPSD -#include "gpsd_iface.hpp" -#endif - -#include <atomic> - -namespace uhd { namespace usrp { namespace e300 { - -static const std::string E300_FPGA_FILE_NAME = "usrp_e300_fpga.bit"; -static const std::string E310_SG1_FPGA_FILE_NAME = "usrp_e310_fpga.bit"; -static const std::string E310_SG3_FPGA_FILE_NAME = "usrp_e310_fpga_sg3.bit"; - -static const std::string E3XX_SG1_FPGA_IDLE_FILE_NAME = "usrp_e3xx_fpga_idle.bit"; -static const std::string E3XX_SG3_FPGA_IDLE_FILE_NAME = "usrp_e3xx_fpga_idle_sg3.bit"; - -static const std::string E300_TEMP_SYSFS = "iio:device0"; -static const std::string E300_SPIDEV_DEVICE  = "/dev/spidev0.1"; -static const std::string E300_I2CDEV_DEVICE  = "/dev/i2c-0"; - -static std::string E300_SERVER_RX_PORT0    = "21756"; -static std::string E300_SERVER_TX_PORT0    = "21757"; -static std::string E300_SERVER_CTRL_PORT0  = "21758"; - -static std::string E300_SERVER_RX_PORT1    = "21856"; -static std::string E300_SERVER_TX_PORT1    = "21857"; -static std::string E300_SERVER_CTRL_PORT1  = "21858"; - - -static std::string E300_SERVER_CODEC_PORT  = "21759"; -static std::string E300_SERVER_GREGS_PORT  = "21760"; -static std::string E300_SERVER_I2C_PORT    = "21761"; -static std::string E300_SERVER_SENSOR_PORT = "21762"; - -static const double E300_RX_SW_BUFF_FULLNESS = 0.9;        //Buffer should be half full -static const size_t E300_RX_FC_REQUEST_FREQ = 5; // per flow ctrl window -static const size_t E300_TX_FC_RESPONSE_FREQ = 8; // per flow ctrl window - -// crossbar settings -static const uint8_t E300_RADIO_DEST_PREFIX_TX   = 0; -static const uint8_t E300_RADIO_DEST_PREFIX_CTRL = 1; -static const uint8_t E300_RADIO_DEST_PREFIX_RX   = 2; - -static const uint8_t E300_XB_DST_AXI = 0; -static const uint8_t E300_XB_DST_RADIO  = 1; -static const uint8_t E300_XB_DST_R1  = 2; -// RFNoC blocks are connected to the first port -// after the last radio (there might be less than 2 -// radios). - -static const uint8_t E300_DEVICE_THERE = 2; -static const uint8_t E300_DEVICE_HERE  = 0; - -static const size_t E300_R0_CTRL_STREAM    = (0 << 2) | E300_RADIO_DEST_PREFIX_CTRL; -static const size_t E300_R0_TX_DATA_STREAM = (0 << 2) | E300_RADIO_DEST_PREFIX_TX; -static const size_t E300_R0_RX_DATA_STREAM = (0 << 2) | E300_RADIO_DEST_PREFIX_RX; - -static const size_t E300_R1_CTRL_STREAM    = (1 << 2) | E300_RADIO_DEST_PREFIX_CTRL; -static const size_t E300_R1_TX_DATA_STREAM = (1 << 2) | E300_RADIO_DEST_PREFIX_TX; -static const size_t E300_R1_RX_DATA_STREAM = (1 << 2) | E300_RADIO_DEST_PREFIX_RX; - -uhd::device_addrs_t e300_find(const uhd::device_addr_t &multi_dev_hint); -void get_e3x0_fpga_images(const uhd::device_addr_t &device_args, -                          std::string &fpga_image, -                          std::string &idle_image); - -/*! - * USRP-E300 implementation guts: - * The implementation details are encapsulated here. - * Handles properties on the mboard, dboard, dsps... - */ -class e300_impl : public uhd::usrp::device3_impl -{ -public: -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    e300_impl(const uhd::device_addr_t &); -    virtual ~e300_impl(void); - -private: // types -    enum compat_t {FPGA_MAJOR, FPGA_MINOR}; - -protected: // methods -    /************************************************************************ -     * Legacy device3 stuff -     ***********************************************************************/ -    void subdev_to_blockid( -            const uhd::usrp::subdev_spec_pair_t &spec, const size_t mb_i, -            rfnoc::block_id_t &block_id, uhd::device_addr_t &block_args -    ); -    uhd::usrp::subdev_spec_pair_t blockid_to_subdev( -            const rfnoc::block_id_t &blockid, const device_addr_t &block_args -    ); - -    /************************************************************************ -     * Transport related -     ***********************************************************************/ -    uhd::device_addr_t get_rx_hints(size_t); - -private: // methods -    /************************************************************************ -     * Initialization -     ***********************************************************************/ -    void _register_loopback_self_test(wb_iface::sptr iface, uint32_t w_addr, uint32_t r_addr); - -    uint32_t _get_version(compat_t which); -    std::string _get_version_hash(void); - -    /************************************************************************ -     * Transport related -     ***********************************************************************/ -    uhd::sid_t _allocate_sid(const uhd::sid_t &address); - -    void _setup_dest_mapping( -        const uhd::sid_t &sid, -        const size_t which_stream); - -    /*! Return the first free AXI channel pair. -     * -     * \throws uhd::runtime_error if no free channel pairs are available. -     */ -    size_t _get_axi_dma_channel_pair(); - -    // For network mode -    uint16_t _get_udp_port( -        uint8_t destination, -        uint8_t prefix); - -    uhd::both_xports_t make_transport( -        const uhd::sid_t &address, -        const xport_type_t type, -        const uhd::device_addr_t &args -    ); - -    uhd::endianness_t get_transport_endianness(size_t) { -        return uhd::ENDIANNESS_LITTLE; -    }; - -    /************************************************************************ -     * Helpers -     ***********************************************************************/ -    void _update_clock_source(const std::string &); - -private: // members -    const uhd::device_addr_t               _device_addr; -    xport_t                                _xport_path; -    e300_fifo_interface::sptr              _fifo_iface; -    std::atomic<size_t>                    _sid_framer; -    boost::dynamic_bitset<>                _dma_chans_available; -    global_regs::sptr                      _global_regs; -    e300_sensor_manager::sptr              _sensor_manager; -    e300_eeprom_manager::sptr              _eeprom_manager; -    uhd::transport::zero_copy_xport_params _data_xport_params; -    uhd::transport::zero_copy_xport_params _ctrl_xport_params; -    std::string                            _idle_image; -    bool                                   _do_not_reload; -#ifdef E300_GPSD -    gpsd_iface::sptr                       _gps; -    static const size_t                    _GPS_TIMEOUT = 5; -#endif -}; - -}}} // namespace uhd::usrp::e300 - -#endif /* INCLUDED_E300_IMPL_HPP */ diff --git a/host/lib/usrp/e300/e300_io_impl.cpp b/host/lib/usrp/e300/e300_io_impl.cpp deleted file mode 100644 index 4460d5616..000000000 --- a/host/lib/usrp/e300/e300_io_impl.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_regs.hpp" -#include "e300_impl.hpp" -#include "e300_fpga_defs.hpp" -#include "e300_defaults.hpp" -#include "../../transport/super_recv_packet_handler.hpp" -#include "../../transport/super_send_packet_handler.hpp" -#include <uhd/utils/tasks.hpp> -#include <boost/bind.hpp> -#include <boost/format.hpp> - -using namespace uhd; -using namespace uhd::usrp; -using namespace uhd::transport; - -namespace uhd { namespace usrp { namespace e300 { - -uhd::device_addr_t e300_impl::get_rx_hints(size_t) -{ -    return uhd::device_addr_t(str(boost::format("max_recv_window=%d") % DEFAULT_RX_DATA_NUM_FRAMES)); -} - -}}} // namespace diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp deleted file mode 100644 index d9a104dda..000000000 --- a/host/lib/usrp/e300/e300_network.cpp +++ /dev/null @@ -1,655 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_network.hpp" - -#ifdef E300_NATIVE - -#include "e300_impl.hpp" - -#include "e300_sensor_manager.hpp" -#include "e300_fifo_config.hpp" -#include "e300_spi.hpp" -#include "e300_i2c.hpp" -#include "e300_defaults.hpp" -#include "e300_common.hpp" -#include "e300_remote_codec_ctrl.hpp" - -#include <uhd/utils/log.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/utils/paths.hpp> - -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> - -#include <boost/asio.hpp> -#include <boost/filesystem.hpp> -#include <boost/make_shared.hpp> - -#include <fstream> -#include <chrono> -#include <thread> - -using namespace uhd; -using namespace uhd::transport; -namespace asio = boost::asio; -namespace fs = boost::filesystem; - -namespace uhd { namespace usrp { namespace e300 { - -static const size_t E300_NETWORK_DEBUG = false; - -static inline bool wait_for_recv_ready(int sock_fd, const size_t timeout_ms) -{ -    //setup timeval for timeout -    timeval tv; -    tv.tv_sec = 0; -    tv.tv_usec = timeout_ms*1000; - -    //setup rset for timeout -    fd_set rset; -    FD_ZERO(&rset); -    FD_SET(sock_fd, &rset); - -    //call select with timeout on receive socket -    return ::select(sock_fd+1, &rset, NULL, NULL, &tv) > 0; -} - -static boost::mutex endpoint_mutex; - -/*********************************************************************** - * Receive tunnel - forwards recv interface to send socket - **********************************************************************/ -static void e300_recv_tunnel( -    const std::string &name, -    uhd::transport::zero_copy_if::sptr recver, -    boost::shared_ptr<asio::ip::udp::socket> sender, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    asio::ip::udp::endpoint _tx_endpoint; -    try -    { -        while (*running) -        { -            //step 1 - get the buffer -            managed_recv_buffer::sptr buff = recver->get_recv_buff(); -            if (not buff) continue; -            if (E300_NETWORK_DEBUG) UHD_LOGGER_INFO("E300") << name << " got " << buff->size(); - -            //step 1.5 -- update endpoint -            { -                boost::mutex::scoped_lock l(endpoint_mutex); -                _tx_endpoint = *endpoint; -            } - -            //step 2 - send to the socket -            sender->send_to(asio::buffer(buff->cast<const void *>(), buff->size()), _tx_endpoint); -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_recv_tunnel exit " << name << " " << ex.what(); -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_recv_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_recv_tunnel exit " << name; -    *running = false; -} - -/*********************************************************************** - * Send tunnel - forwards recv socket to send interface - **********************************************************************/ -static void e300_send_tunnel( -    const std::string &name, -    boost::shared_ptr<asio::ip::udp::socket> recver, -    uhd::transport::zero_copy_if::sptr sender, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    asio::ip::udp::endpoint _rx_endpoint; -    try -    { -        while (*running) -        { -            //step 1 - get the buffer -            managed_send_buffer::sptr buff = sender->get_send_buff(); -            if (not buff) continue; - -            //step 2 - recv from socket -            while (not wait_for_recv_ready(recver->native_handle(), 100) and *running){} -            if (not *running) break; -            const size_t num_bytes = recver->receive_from(asio::buffer(buff->cast<void *>(), buff->size()), _rx_endpoint); -            if (E300_NETWORK_DEBUG) UHD_LOGGER_INFO("E300") << name << " got " << num_bytes; - -            //step 2.5 -- update endpoint -            { -                boost::mutex::scoped_lock l(endpoint_mutex); -                *endpoint = _rx_endpoint; -            } - -            //step 3 - commit the buffer -            buff->commit(num_bytes); -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_send_tunnel exit " << name << " " << ex.what() ; -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_send_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_send_tunnel exit " << name; -    *running = false; -} - -static void e300_codec_ctrl_tunnel( -    const std::string &name, -    boost::shared_ptr<asio::ip::udp::socket> socket, -    ad9361_ctrl::sptr _codec_ctrl, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    asio::ip::udp::endpoint _endpoint; -    try -    { -        while (*running) -        { -            uint8_t in_buff[64] = {}; -            uint8_t out_buff[64] = {}; - -            const size_t num_bytes = socket->receive_from(asio::buffer(in_buff), *endpoint); - -            typedef e300_remote_codec_ctrl::transaction_t codec_xact_t; - -            if (num_bytes < sizeof(codec_xact_t)) { -                std::cout << "Received short packet of " << num_bytes  << std::endl; -                continue; -            } - -            codec_xact_t *in = reinterpret_cast<codec_xact_t*>(in_buff); -            codec_xact_t *out = reinterpret_cast<codec_xact_t*>(out_buff); -            std::memcpy(out, in, sizeof(codec_xact_t)); - -            std::string which_str; -            switch (uhd::ntohx<uint32_t>(in->which)) { -            case codec_xact_t::CHAIN_TX1: -                which_str = "TX1"; break; -            case codec_xact_t::CHAIN_TX2: -                which_str = "TX2"; break; -            case codec_xact_t::CHAIN_RX1: -                which_str = "RX1"; break; -            case codec_xact_t::CHAIN_RX2: -                which_str = "RX2"; break; -            default: -                which_str = ""; break; -            } - -            switch (uhd::ntohx<uint32_t>(in->action)) { -            case codec_xact_t::ACTION_SET_GAIN: -                out->gain = _codec_ctrl->set_gain(which_str, in->gain); -                break; -            case codec_xact_t::ACTION_SET_CLOCK_RATE: -                out->rate = _codec_ctrl->set_clock_rate(in->rate); -                break; -            case codec_xact_t::ACTION_SET_ACTIVE_CHANS: -                _codec_ctrl->set_active_chains( -                    uhd::ntohx<uint32_t>(in->bits) & (1<<0), -                    uhd::ntohx<uint32_t>(in->bits) & (1<<1), -                    uhd::ntohx<uint32_t>(in->bits) & (1<<2), -                    uhd::ntohx<uint32_t>(in->bits) & (1<<3)); -                break; -            case codec_xact_t::ACTION_TUNE: -                out->freq = _codec_ctrl->tune(which_str, in->freq); -                break; -            case codec_xact_t::ACTION_GET_FREQ: -                    out->freq = _codec_ctrl->get_freq(which_str); -                break; -            case codec_xact_t::ACTION_SET_LOOPBACK: -                _codec_ctrl->data_port_loopback( -                    uhd::ntohx<uint32_t>(in->bits) & 1); -                break; -            case codec_xact_t::ACTION_GET_RSSI: -                out->rssi = _codec_ctrl->get_rssi(which_str).to_real(); -                break; -            case codec_xact_t::ACTION_GET_TEMPERATURE: -                out->temp = _codec_ctrl->get_temperature().to_real(); -                break; -            case codec_xact_t::ACTION_SET_DC_OFFSET_AUTO: -                _codec_ctrl->set_dc_offset_auto(which_str, in->use_dc_correction == 1); -                break; -            case codec_xact_t::ACTION_SET_IQ_BALANCE_AUTO: -                _codec_ctrl->set_iq_balance_auto(which_str, in->use_iq_correction == 1); -            case codec_xact_t::ACTION_SET_AGC: -                _codec_ctrl->set_agc(which_str, in->use_agc == 1); -                break; -            case codec_xact_t::ACTION_SET_AGC_MODE: -                if(in->agc_mode == 0) { -                    _codec_ctrl->set_agc_mode(which_str, "slow"); -                } else if (in->agc_mode == 1) { -                    _codec_ctrl->set_agc_mode(which_str, "fast"); -                } -                break; -            case codec_xact_t::ACTION_SET_BW: -                out->bw = _codec_ctrl->set_bw_filter(which_str, in->bw); -                break; -            default: -                UHD_LOGGER_INFO("E300") << "Got unknown request?!"; -                //Zero out actions to fail this request on client -                out->action = uhd::htonx<uint32_t>(0); -            } - -            socket->send_to(asio::buffer(out_buff, 64), *endpoint); -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_ctrl_tunnel exit " << name << " " << ex.what() ; -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_ctrl_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_ctrl_tunnel exit " << name; -    *running = false; -} - -static void e300_global_regs_tunnel( -    const std::string &name, -    boost::shared_ptr<asio::ip::udp::socket> socket, -    global_regs::sptr regs, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    UHD_ASSERT_THROW(regs); -    asio::ip::udp::endpoint _endpoint; -    try -    { -        while (*running) -        { -            uint8_t in_buff[16] = {}; - -            const size_t num_bytes = socket->receive_from(asio::buffer(in_buff), *endpoint); - -            if (num_bytes < 16) { -                std::cout << "Received short packet: " << num_bytes << std::endl; -                continue; -            } - -            global_regs_transaction_t *in = -                reinterpret_cast<global_regs_transaction_t *>(in_buff); - -            if(uhd::ntohx<uint32_t>(in->is_poke)) { -                regs->poke32(uhd::ntohx<uint32_t>(in->addr), uhd::ntohx<uint32_t>(in->data)); -            } -            else { -                in->data = uhd::htonx<uint32_t>(regs->peek32(uhd::ntohx<uint32_t>(in->addr))); -                socket->send_to(asio::buffer(in_buff, 16), *endpoint); -            } -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_gregs_tunnel exit " << name << " " << ex.what() ; -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_gregs_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_gregs_tunnel exit " << name; -    *running = false; -} - -static void e300_sensor_tunnel( -    const std::string &name, -    boost::shared_ptr<asio::ip::udp::socket> socket, -    e300_sensor_manager::sptr sensor_manager, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    asio::ip::udp::endpoint _endpoint; -    try -    { -        while (*running) -        { -            uint8_t in_buff[128] = {}; - -            const size_t num_bytes = socket->receive_from(asio::buffer(in_buff), *endpoint); - -            if (num_bytes < sizeof(sensor_transaction_t)) { -                std::cout << "Received short packet: " << num_bytes << std::endl; -                continue; -            } - -            uhd::usrp::e300::sensor_transaction_t *in = -                reinterpret_cast<uhd::usrp::e300::sensor_transaction_t *>(in_buff); - -            if (uhd::ntohx(in->which) == ZYNQ_TEMP) { -                sensor_value_t temp = sensor_manager->get_mb_temp(); -                // TODO: This is ugly ... use proper serialization -                in->value = uhd::htonx<uint32_t>( -                    e300_sensor_manager::pack_float_in_uint32_t(temp.to_real())); -            } else if (uhd::ntohx(in->which) == REF_LOCK) { -                in->value = uhd::htonx<uint32_t>( -                    sensor_manager->get_ref_lock().to_bool() ? 1 : 0); -            } else -                UHD_LOGGER_INFO("E300") << "Got unknown request?!"; - -            socket->send_to(asio::buffer(in_buff, sizeof(sensor_transaction_t)), *endpoint); -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_sensor_tunnel exit " << name << " " << ex.what() ; -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_sensor_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_sensor_tunnel exit " << name; -    *running = false; -} - -static void e300_i2c_tunnel( -    const std::string &name, -    boost::shared_ptr<asio::ip::udp::socket> socket, -    uhd::usrp::e300::i2c::sptr i2c, -    asio::ip::udp::endpoint *endpoint, -    bool *running -) -{ -    UHD_ASSERT_THROW(i2c); -    asio::ip::udp::endpoint _endpoint; -    try -    { -        while (*running) -        { -            uint8_t in_buff[sizeof(uhd::usrp::e300::i2c_transaction_t)]; - -            const size_t num_bytes = socket->receive_from(asio::buffer(in_buff), *endpoint); - -            if (num_bytes < sizeof(uhd::usrp::e300::i2c_transaction_t)) { -                std::cout << "Received short packet: " << num_bytes << std::endl; -                continue; -            } - -            uhd::usrp::e300::i2c_transaction_t *in = -                reinterpret_cast<uhd::usrp::e300::i2c_transaction_t *>(in_buff); - -            // byte addressed accesses go through here -            if(in->type & i2c::ONEBYTE) { -                if(in->type & i2c::WRITE) { -                    i2c->set_i2c_reg8( -                        in->addr, -                        uhd::ntohx<uint16_t>(in->reg), in->data); -                } else { -                    in->data = i2c->get_i2c_reg8(in->addr, uhd::ntohx<uint16_t>(in->reg)); -                    socket->send_to(asio::buffer(in_buff, sizeof(in_buff)), *endpoint); -                } - -            // 2 byte addressed accesses go through here -            } else if (in->type & i2c::TWOBYTE) { -                if(in->type & i2c::WRITE) { -                    i2c->set_i2c_reg16( -                        in->addr, -                        uhd::ntohx<uint16_t>(in->reg), in->data); -                } else { -                    in->data = i2c->get_i2c_reg16(in->addr, uhd::ntohx<uint16_t>(in->reg)); -                    socket->send_to(asio::buffer(in_buff, sizeof(in_buff)), *endpoint); -                } - -            } else { -                UHD_LOGGER_ERROR("E300") << "e300_i2c_tunnel could not handle message." ; -            } -        } -    } -    catch(const std::exception &ex) -    { -        UHD_LOGGER_ERROR("E300") << "e300_i2c_tunnel exit " << name << " " << ex.what() ; -    } -    catch(...) -    { -        UHD_LOGGER_ERROR("E300") << "e300_i2c_tunnel exit " << name ; -    } -    UHD_LOGGER_INFO("E300") << "e300_i2c_tunnel exit " << name; -    *running = false; -} - - - - -class network_server_impl : public network_server -{ -public: -    network_server_impl(const uhd::device_addr_t &device_addr); -    virtual ~network_server_impl(void); -    void run(void); - -private: -    struct xports_t -    { -        uhd::transport::zero_copy_if::sptr send_ctrl_xport; -        uhd::transport::zero_copy_if::sptr recv_ctrl_xport; -        uhd::transport::zero_copy_if::sptr tx_data_xport; -        uhd::transport::zero_copy_if::sptr tx_flow_xport; -        uhd::transport::zero_copy_if::sptr rx_data_xport; -        uhd::transport::zero_copy_if::sptr rx_flow_xport; -    }; - -private: -    void _run_server( -        const std::string &port, -        const std::string &what, -        const size_t fe); - -private: -    boost::shared_ptr<e300_fifo_interface>   _fifo_iface; -    xports_t                                 _xports[2]; -    boost::shared_ptr<ad9361_ctrl>           _codec_ctrl; -    boost::shared_ptr<global_regs>           _global_regs; -    boost::shared_ptr<e300_sensor_manager>   _sensor_manager; -    boost::shared_ptr<e300_eeprom_manager>   _eeprom_manager; -}; - -network_server_impl::~network_server_impl(void) -{ -} - -/*********************************************************************** - * The UDP server itself - **********************************************************************/ -void network_server_impl::_run_server( -    const std::string &port, -    const std::string &what, -    const size_t fe) -{ -    asio::io_service io_service; -    asio::ip::udp::resolver resolver(io_service); -    asio::ip::udp::resolver::query query(asio::ip::udp::v4(), "0.0.0.0", port); -    asio::ip::udp::endpoint endpoint = *resolver.resolve(query); - -    //boost::shared_ptr<asio::ip::udp::acceptor> acceptor(new asio::ip::udp::acceptor(io_service, endpoint)); -    while (not boost::this_thread::interruption_requested()) -    { -        UHD_LOGGER_INFO("E300") << "e300 run server on port " << port << " for " << what; -        try -        { -            //while (not wait_for_recv_ready(acceptor->native(), 100)) -            //{ -            //    if (boost::this_thread::interruption_requested()) return; -            //} -            boost::shared_ptr<asio::ip::udp::socket> socket; -            socket.reset(new asio::ip::udp::socket(io_service, endpoint)); -            //acceptor->accept(*socket); -            UHD_LOGGER_INFO("E300") << "e300 socket accept on port " << port << " for " << what; -            //asio::ip::udp::no_delay option(true); -            //socket->set_option(option); -            boost::thread_group tg; -            bool running = true; -            xports_t &perif = _xports[fe]; -            if (what == "RX") { -                tg.create_thread(boost::bind(&e300_recv_tunnel, "RX data tunnel", perif.rx_data_xport, socket, &endpoint, &running)); -                tg.create_thread(boost::bind(&e300_send_tunnel, "RX flow tunnel", socket, perif.rx_flow_xport, &endpoint, &running)); -            } -            if (what == "TX") { -                tg.create_thread(boost::bind(&e300_recv_tunnel, "TX flow tunnel", perif.tx_flow_xport, socket, &endpoint, &running)); -                tg.create_thread(boost::bind(&e300_send_tunnel, "TX data tunnel", socket, perif.tx_data_xport, &endpoint, &running)); -            } -            if (what == "CTRL") { -                tg.create_thread(boost::bind(&e300_recv_tunnel, "response tunnel", perif.recv_ctrl_xport, socket, &endpoint, &running)); -                tg.create_thread(boost::bind(&e300_send_tunnel, "control tunnel", socket, perif.send_ctrl_xport, &endpoint, &running)); -            } -            if (what == "CODEC") { -                tg.create_thread(boost::bind(&e300_codec_ctrl_tunnel, "CODEC tunnel", socket, _codec_ctrl, &endpoint, &running)); -            } -            if (what == "I2C") { -                tg.create_thread(boost::bind(&e300_i2c_tunnel, "I2C tunnel", socket, _eeprom_manager->get_i2c_sptr(), &endpoint, &running)); -            } -            if (what == "GREGS") { -                tg.create_thread(boost::bind(&e300_global_regs_tunnel, "GREGS tunnel", socket, _global_regs, &endpoint, &running)); -            } -            if (what == "SENSOR") { -                tg.create_thread(boost::bind(&e300_sensor_tunnel, "SENSOR tunnel", socket, _sensor_manager, &endpoint, &running)); -            } - -            tg.join_all(); -            socket->close(); -            socket.reset(); -        } -        catch(...){} -    } -} - -void network_server_impl::run() -{ -    for(;;) -    { -        boost::thread_group tg; -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_RX_PORT0, "RX",0)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_TX_PORT0, "TX",0)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_CTRL_PORT0, "CTRL",0)); - -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_RX_PORT1, "RX",1)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_TX_PORT1, "TX",1)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_CTRL_PORT1, "CTRL",1)); - -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_SENSOR_PORT, "SENSOR", 0 /*don't care */)); - -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_CODEC_PORT, "CODEC", 0 /*don't care */)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_GREGS_PORT, "GREGS", 0 /*don't care */)); -        tg.create_thread(boost::bind(&network_server_impl::_run_server, this, E300_SERVER_I2C_PORT, "I2C", 0 /*don't care */)); -        tg.join_all(); -    } -} -network_server_impl::network_server_impl(const uhd::device_addr_t &device_addr) -{ -    _eeprom_manager = boost::make_shared<e300_eeprom_manager>(i2c::make_i2cdev(E300_I2CDEV_DEVICE)); -    if (not device_addr.has_key("no_reload_fpga")) { -        // Load FPGA image if provided via args -        if (device_addr.has_key("fpga")) { -            common::load_fpga_image(device_addr["fpga"]); -        // Else load the FPGA image based on the product ID -        } else { -            //extract the FPGA path for the e300 -            const uint16_t pid = boost::lexical_cast<uint16_t>( -                _eeprom_manager->get_mb_eeprom()["product"]); -            std::string fpga_image; -            switch(e300_eeprom_manager::get_mb_type(pid)) { -            case e300_eeprom_manager::USRP_E310_SG1_MB: -                fpga_image = find_image_path(E310_SG1_FPGA_FILE_NAME); -                break; -            case e300_eeprom_manager::USRP_E310_SG3_MB: -                fpga_image = find_image_path(E310_SG3_FPGA_FILE_NAME); -                break; -            case e300_eeprom_manager::USRP_E300_MB: -                fpga_image = find_image_path(E300_FPGA_FILE_NAME); -                break; -            case e300_eeprom_manager::UNKNOWN: -            default: -                UHD_LOGGER_WARNING("E300") << "Unknown motherboard type, loading e300 image." -                                 ; -                fpga_image = find_image_path(E300_FPGA_FILE_NAME); -                break; -            } -            common::load_fpga_image(fpga_image); -        } -    } - -    uhd::transport::zero_copy_xport_params ctrl_xport_params; -    ctrl_xport_params.recv_frame_size = e300::DEFAULT_CTRL_FRAME_SIZE; -    ctrl_xport_params.num_recv_frames = e300::DEFAULT_CTRL_NUM_FRAMES; -    ctrl_xport_params.send_frame_size = e300::DEFAULT_CTRL_FRAME_SIZE; -    ctrl_xport_params.num_send_frames = e300::DEFAULT_CTRL_NUM_FRAMES; - -    uhd::transport::zero_copy_xport_params data_xport_params; -    data_xport_params.recv_frame_size = device_addr.cast<size_t>("recv_frame_size", e300::DEFAULT_RX_DATA_FRAME_SIZE); -    data_xport_params.num_recv_frames = device_addr.cast<size_t>("num_recv_frames", e300::DEFAULT_RX_DATA_NUM_FRAMES); -    data_xport_params.send_frame_size = device_addr.cast<size_t>("send_frame_size", e300::DEFAULT_TX_DATA_FRAME_SIZE); -    data_xport_params.num_send_frames = device_addr.cast<size_t>("num_send_frames", e300::DEFAULT_TX_DATA_NUM_FRAMES); -    // until we figure out why this goes wrong we'll keep this hack around -    data_xport_params.recv_frame_size = -        std::min(e300::MAX_NET_RX_DATA_FRAME_SIZE, data_xport_params.recv_frame_size); -    data_xport_params.send_frame_size = -        std::min(e300::MAX_NET_TX_DATA_FRAME_SIZE, data_xport_params.send_frame_size); - - -    e300_fifo_config_t fifo_cfg; -    try { -        fifo_cfg = e300_read_sysfs(); -    } catch (uhd::lookup_error &e) { -        throw uhd::runtime_error("Failed to get driver parameters from sysfs."); -    } -    _fifo_iface = e300_fifo_interface::make(fifo_cfg); -    _global_regs = global_regs::make(_fifo_iface->get_global_regs_base()); - -    // static mapping, boooohhhhhh -    _xports[0].send_ctrl_xport = _fifo_iface->make_send_xport(E300_R0_CTRL_STREAM, ctrl_xport_params); -    _xports[0].recv_ctrl_xport = _fifo_iface->make_recv_xport(E300_R0_CTRL_STREAM, ctrl_xport_params); -    _xports[0].tx_data_xport   = _fifo_iface->make_send_xport(E300_R0_TX_DATA_STREAM, data_xport_params); -    _xports[0].tx_flow_xport   = _fifo_iface->make_recv_xport(E300_R0_TX_DATA_STREAM, ctrl_xport_params); -    _xports[0].rx_data_xport   = _fifo_iface->make_recv_xport(E300_R0_RX_DATA_STREAM, data_xport_params); -    _xports[0].rx_flow_xport   = _fifo_iface->make_send_xport(E300_R0_RX_DATA_STREAM, ctrl_xport_params); - -    _xports[1].send_ctrl_xport = _fifo_iface->make_send_xport(E300_R1_CTRL_STREAM, ctrl_xport_params); -    _xports[1].recv_ctrl_xport = _fifo_iface->make_recv_xport(E300_R1_CTRL_STREAM, ctrl_xport_params); -    _xports[1].tx_data_xport   = _fifo_iface->make_send_xport(E300_R1_TX_DATA_STREAM, data_xport_params); -    _xports[1].tx_flow_xport   = _fifo_iface->make_recv_xport(E300_R1_TX_DATA_STREAM, ctrl_xport_params); -    _xports[1].rx_data_xport   = _fifo_iface->make_recv_xport(E300_R1_RX_DATA_STREAM, data_xport_params); -    _xports[1].rx_flow_xport   = _fifo_iface->make_send_xport(E300_R1_RX_DATA_STREAM, ctrl_xport_params); - -    ad9361_params::sptr client_settings = boost::make_shared<e300_ad9361_client_t>(); -    _codec_ctrl = ad9361_ctrl::make_spi(client_settings, spi::make(E300_SPIDEV_DEVICE), 1); -    // This is horrible ... why do I have to sleep here? -    std::this_thread::sleep_for(std::chrono::milliseconds(100)); -    _sensor_manager = e300_sensor_manager::make_local(_global_regs); -} - -}}} // namespace - -using namespace uhd::usrp::e300; - -network_server::sptr network_server::make(const uhd::device_addr_t &device_addr) -{ -    return sptr(new network_server_impl(device_addr)); -} - -#else - -using namespace uhd::usrp::e300; - -network_server::sptr network_server::make(const uhd::device_addr_t &) -{ -    throw uhd::assertion_error("network_server::make() !E300_NATIVE"); -} -#endif diff --git a/host/lib/usrp/e300/e300_network.hpp b/host/lib/usrp/e300/e300_network.hpp deleted file mode 100644 index caa25b0ad..000000000 --- a/host/lib/usrp/e300/e300_network.hpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_NETWORK_HPP -#define INCLUDED_E300_NETWORK_HPP - -#include <string> -#include <uhd/utils/noncopyable.hpp> - -#include <uhd/device.hpp> - - -static const std::string E310_FPGA_FILE_NAME = "usrp_e310_fpga.bit"; -static const std::string E300_FPGA_FILE_NAME = "usrp_e300_fpga.bit"; - -namespace uhd { namespace usrp { namespace e300 { - -class UHD_API network_server : uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<network_server> sptr; -    virtual void run(void) = 0; - -    static sptr make(const uhd::device_addr_t &device_addr); -}; - - -}}} -#endif // INCLUDED_E300_NETWORK_HPP diff --git a/host/lib/usrp/e300/e300_regs.hpp b/host/lib/usrp/e300/e300_regs.hpp deleted file mode 100644 index 88d58907b..000000000 --- a/host/lib/usrp/e300/e300_regs.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2012-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_REGS_HPP -#define INCLUDED_E300_REGS_HPP - -#include <stdint.h> -#include <uhd/config.hpp> - -static const uint32_t VCRX_V2     = 15; -static const uint32_t VCRX_V1     = 14; -static const uint32_t VCTXRX_V2   = 13; -static const uint32_t VCTXRX_V1   = 12; -static const uint32_t TX_ENABLEB  = 11; -static const uint32_t TX_ENABLEA  = 10; -static const uint32_t RXC_BANDSEL = 8; -static const uint32_t RXB_BANDSEL = 6; -static const uint32_t RX_BANDSEL  = 3; -static const uint32_t TX_BANDSEL  = 0; - -#endif /* INCLUDED_E300_REGS_HPP */ diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp deleted file mode 100644 index 5692a138e..000000000 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ /dev/null @@ -1,285 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_remote_codec_ctrl.hpp" - -#include <stdint.h> -#include <uhd/exception.hpp> -#include <uhd/utils/byteswap.hpp> -#include <cstring> -#include <iostream> - -namespace uhd { namespace usrp { namespace e300 { - -class e300_remote_codec_ctrl_impl : public e300_remote_codec_ctrl -{ -public: -    e300_remote_codec_ctrl_impl(uhd::transport::zero_copy_if::sptr xport) : _xport(xport) -    { -    } - -    virtual ~e300_remote_codec_ctrl_impl(void) -    { -    } - - -    double set_gain(const std::string &which, const double value) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_GAIN); -        if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.gain = value; - -        _transact(); -        return _retval.gain; -    } - -    double set_clock_rate(const double rate) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>( -            transaction_t::ACTION_SET_CLOCK_RATE); -        _args.which = uhd::htonx<uint32_t>( -            transaction_t::CHAIN_NONE);  /*Unused*/ -        _args.rate = rate; - -        _transact(); -        return _retval.gain; -    } - -    void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>( -            transaction_t::ACTION_SET_ACTIVE_CHANS); -        /*Unused*/ -        _args.which = uhd::htonx<uint32_t>( -            transaction_t::CHAIN_NONE); -        _args.bits = uhd::htonx<uint32_t>( -                     (tx1 ? (1<<0) : 0) | -                     (tx2 ? (1<<1) : 0) | -                     (rx1 ? (1<<2) : 0) | -                     (rx2 ? (1<<3) : 0)); - -        _transact(); -    } - -    double tune(const std::string &which, const double value) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_TUNE); -        if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.freq = value; - -        _transact(); -        return _retval.freq; -    } - -    double get_freq(const std::string &which) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_GET_FREQ); -        if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); - -        _transact(); -        return _retval.freq; -    } - -    void data_port_loopback(const bool on) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_LOOPBACK); -        _args.which  = uhd::htonx<uint32_t>(transaction_t::CHAIN_NONE);  /*Unused*/ -        _args.bits = uhd::htonx<uint32_t>(on ? 1 : 0); - -        _transact(); -    } - -    sensor_value_t get_rssi(const std::string &which) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_GET_RSSI); -        if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.bits = uhd::htonx<uint32_t>(0); - -        _transact(); -        return sensor_value_t("RSSI", _retval.rssi, "dB"); -    } - -    sensor_value_t get_temperature() -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_GET_TEMPERATURE); -        _args.which  = uhd::htonx<uint32_t>(transaction_t::CHAIN_NONE);  /*Unused*/ -        _args.bits = uhd::htonx<uint32_t>(0); - -        _transact(); -        return sensor_value_t("temp", _retval.temp, "C"); -    } - -    void set_dc_offset_auto(const std::string &which, const bool on) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_DC_OFFSET_AUTO); -        if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.use_dc_correction = on ? 1 : 0; - -        _transact(); -    } - -    void set_iq_balance_auto(const std::string &which, const bool on) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_IQ_BALANCE_AUTO); -        if (which == "TX1")     _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.use_iq_correction = on ? 1 : 0; - -        _transact(); -    } - -    void set_agc(const std::string &which, bool enable) -    { -        _clear(); -       _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_AGC); -       if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -       else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -       else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -       else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -       else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -       _args.use_agc = enable ? 1 : 0; - -       _transact(); -    } - -    void set_agc_mode(const std::string &which, const std::string &mode) -    { -        _clear(); -       _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_AGC_MODE); - -       if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -       else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -       else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -       else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -       else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); - -       if(mode == "slow") { -           _args.agc_mode = 0; -       } else if (mode == "fast") { -           _args.agc_mode = 1; -       } else { -           throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect agc mode."); -       } - -       _transact(); -    } - -    //! set the filter bandwidth for the frontend's analog low pass -    double set_bw_filter(const std::string &which, const double bw) -    { -        _clear(); -        _args.action = uhd::htonx<uint32_t>(transaction_t::ACTION_SET_BW); -        if (which == "TX1")      _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX1); -        else if (which == "TX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_TX2); -        else if (which == "RX1") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX1); -        else if (which == "RX2") _args.which = uhd::htonx<uint32_t>(transaction_t::CHAIN_RX2); -        else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); -        _args.bw = bw; - -        _transact(); -        return _retval.bw; -    } - -    //! List all available filters by name -    std::vector<std::string> get_filter_names(const std::string &) -    { -        return std::vector<std::string>(); -    } - -    //! Return a list of all filters -    filter_info_base::sptr get_filter(const std::string &, const std::string &) -    { -        UHD_THROW_INVALID_CODE_PATH(); -    } - -    //! Write back a filter -    void set_filter(const std::string &, const std::string &, const filter_info_base::sptr) -    { -        UHD_LOGGER_WARNING("E300") << "Attempting to set filter on E300 in network mode." ; -    } - -    void output_digital_test_tone(UHD_UNUSED(bool enb)) -    { -        UHD_THROW_INVALID_CODE_PATH(); -    } - -    void set_timing_mode(UHD_UNUSED(const std::string &timing_mode)) -    { -        UHD_THROW_INVALID_CODE_PATH(); -    } - -private: -    void _transact() { -        { -            uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); -            if (not buff or buff->size() < sizeof(_args)) -                throw std::runtime_error("e300_remote_codec_ctrl_impl send timeout"); -            std::memcpy(buff->cast<void *>(), &_args, sizeof(_args)); -            buff->commit(sizeof(_args)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); -            if (not buff or buff->size() < sizeof(_retval)) -                throw std::runtime_error("e300_remote_codec_ctrl_impl recv timeout"); -            std::memcpy(&_retval, buff->cast<const void *>(), sizeof(_retval)); -        } - -        if (_args.action != _retval.action) -            throw std::runtime_error("e300_remote_codec_ctrl_impl transaction failed."); -    } - -    void _clear() { -        _args.action = 0; -        _args.which = 0; -        _args.bits = 0; -        _retval.action = 0; -        _retval.which = 0; -        _retval.bits = 0; -    } - -    uhd::transport::zero_copy_if::sptr _xport; -    transaction_t                      _args; -    transaction_t                      _retval; -}; - -ad9361_ctrl::sptr e300_remote_codec_ctrl::make(uhd::transport::zero_copy_if::sptr xport) -{ -    return sptr(new e300_remote_codec_ctrl_impl(xport)); -} - -}}}; diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp deleted file mode 100644 index 9c9e16672..000000000 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_REMOTE_CODEC_CTRL_HPP -#define INCLUDED_E300_REMOTE_CODEC_CTRL_HPP - -#include <uhd/transport/zero_copy.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -class e300_remote_codec_ctrl : public uhd::usrp::ad9361_ctrl -{ -public: -    struct transaction_t { -        uint32_t     action; -        uint32_t     which; -        union { -            double          rate; -            double          gain; -            double          freq; -            double          rssi; -            double          temp; -            double          bw; -            uint32_t use_dc_correction; -            uint32_t use_iq_correction; -            uint32_t use_agc; -            uint32_t agc_mode; -            uint64_t bits; -        }; - -        //Actions -        static const uint32_t ACTION_SET_GAIN            = 10; -        static const uint32_t ACTION_SET_CLOCK_RATE      = 11; -        static const uint32_t ACTION_SET_ACTIVE_CHANS    = 12; -        static const uint32_t ACTION_TUNE                = 13; -        static const uint32_t ACTION_SET_LOOPBACK        = 14; -        static const uint32_t ACTION_GET_RSSI            = 15; -        static const uint32_t ACTION_GET_TEMPERATURE     = 16; -        static const uint32_t ACTION_SET_DC_OFFSET_AUTO  = 17; -        static const uint32_t ACTION_SET_IQ_BALANCE_AUTO = 18; -        static const uint32_t ACTION_SET_AGC             = 19; -        static const uint32_t ACTION_SET_AGC_MODE        = 20; -        static const uint32_t ACTION_SET_BW              = 21; -        static const uint32_t ACTION_GET_FREQ            = 22; - -        //Values for "which" -        static const uint32_t CHAIN_NONE = 0; -        static const uint32_t CHAIN_TX1  = 1; -        static const uint32_t CHAIN_TX2  = 2; -        static const uint32_t CHAIN_RX1  = 3; -        static const uint32_t CHAIN_RX2  = 4; -    }; - -    static sptr make(uhd::transport::zero_copy_if::sptr xport); -}; - -}}}; - -#endif /* INCLUDED_E300_REMOTE_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/e300/e300_sensor_manager.cpp b/host/lib/usrp/e300/e300_sensor_manager.cpp deleted file mode 100644 index fda1f3f80..000000000 --- a/host/lib/usrp/e300/e300_sensor_manager.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include "e300_sensor_manager.hpp" - -#include <boost/thread.hpp> -#include <boost/assign/list_of.hpp> -#include <boost/format.hpp> - -#include <cstring> -#include <uhd/exception.hpp> -#include <uhd/utils/byteswap.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -class e300_sensor_proxy : public e300_sensor_manager -{ -public: -    e300_sensor_proxy( -        uhd::transport::zero_copy_if::sptr xport) : _xport(xport) -    { -    } - -    std::vector<std::string> get_sensors() -    { -        return boost::assign::list_of("temp")("ref_locked"); -    } - -    uhd::sensor_value_t get_sensor(const std::string &key) -    { -        if (key == "temp") -            return get_mb_temp(); -        else if (key == "ref_locked") -            return get_ref_lock(); -        else -            throw uhd::lookup_error( -                str(boost::format("Invalid sensor %s requested.") % key)); -    } - -    uhd::sensor_value_t get_mb_temp(void) -    { -        boost::mutex::scoped_lock(_mutex); -        sensor_transaction_t transaction; -        transaction.which = uhd::htonx<uint32_t>(ZYNQ_TEMP); -        { -            uhd::transport::managed_send_buffer::sptr buff -                = _xport->get_send_buff(1.0); -            if (not buff or buff->size() < sizeof(transaction)) { -                throw uhd::runtime_error("sensor proxy send timeout"); -            } -            std::memcpy( -                buff->cast<void *>(), -                &transaction, -                sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff -                = _xport->get_recv_buff(1.0); - -            if (not buff or buff->size() < sizeof(transaction)) -                throw uhd::runtime_error("sensor proxy recv timeout"); - -            std::memcpy( -                &transaction, -                buff->cast<const void *>(), -                sizeof(transaction)); -        } -        UHD_ASSERT_THROW(uhd::ntohx<uint32_t>(transaction.which) == ZYNQ_TEMP); -        // TODO: Use proper serialization here ... -        return sensor_value_t( -            "temp", -            e300_sensor_manager::unpack_float_from_uint32_t( -                uhd::ntohx(transaction.value)), -            "C"); -    } - -    uhd::sensor_value_t get_ref_lock(void) -    { -        boost::mutex::scoped_lock(_mutex); -        sensor_transaction_t transaction; -        transaction.which = uhd::htonx<uint32_t>(REF_LOCK); -        { -            uhd::transport::managed_send_buffer::sptr buff -                = _xport->get_send_buff(1.0); -            if (not buff or buff->size() < sizeof(transaction)) { -                throw uhd::runtime_error("sensor proxy send timeout"); -            } -            std::memcpy( -                buff->cast<void *>(), -                &transaction, -                sizeof(transaction)); -            buff->commit(sizeof(transaction)); -        } -        { -            uhd::transport::managed_recv_buffer::sptr buff -                = _xport->get_recv_buff(1.0); - -            if (not buff or buff->size() < sizeof(transaction)) -                throw uhd::runtime_error("sensor proxy recv timeout"); - -            std::memcpy( -                &transaction, -                buff->cast<const void *>(), -                sizeof(transaction)); -        } -        UHD_ASSERT_THROW(uhd::ntohx<uint32_t>(transaction.which) == REF_LOCK); -        // TODO: Use proper serialization here ... -        return sensor_value_t("Ref", (uhd::ntohx(transaction.value) > 0), "locked", "unlocked"); -    } - -private: -    uhd::transport::zero_copy_if::sptr _xport; -    boost::mutex                       _mutex; -}; - -}}} // namespace - -using namespace uhd::usrp::e300; - -e300_sensor_manager::sptr e300_sensor_manager::make_proxy( -    uhd::transport::zero_copy_if::sptr xport) -{ -    return sptr(new e300_sensor_proxy(xport)); -} - -#ifdef E300_NATIVE -#include "e300_fifo_config.hpp" - -namespace uhd { namespace usrp { namespace e300 { - -static const std::string E300_TEMP_SYSFS = "iio:device0"; - -class e300_sensor_local : public e300_sensor_manager -{ -public: -    e300_sensor_local(global_regs::sptr global_regs) : -        _global_regs(global_regs) -    { -    } - -    std::vector<std::string> get_sensors() -    { -        return boost::assign::list_of("temp")("ref_locked"); -    } - -    uhd::sensor_value_t get_sensor(const std::string &key) -    { -        if (key == "temp") -            return get_mb_temp(); -        else if (key == "ref_locked") -            return get_ref_lock(); -        else -            throw uhd::lookup_error( -                str(boost::format("Invalid sensor %s requested.") % key)); -    } - -    uhd::sensor_value_t get_mb_temp(void) -    { -        double scale = std::stod( -            e300_get_sysfs_attr(E300_TEMP_SYSFS, "in_temp0_scale")); -        unsigned long raw = std::stoul( -            e300_get_sysfs_attr(E300_TEMP_SYSFS, "in_temp0_raw")); -        unsigned long offset = std::stoul( -            e300_get_sysfs_attr(E300_TEMP_SYSFS, "in_temp0_offset")); -        return sensor_value_t("temp", (raw + offset) * scale / 1000, "C"); -    } - -    uhd::sensor_value_t get_ref_lock(void) -    { -        //PPSLOOP_LOCKED_MASK is asserted in the following cases: -        //- (Time source = GPS or External) AND (Loop is locked and is in fine adj mode) -        //- Time source is Internal -        static const uint32_t PPSLOOP_LOCKED_MASK = 0x04; -        static const uint32_t REFPLL_LOCKED_MASK = 0x20; - -        const uint32_t status = -            _global_regs->peek32(global_regs::RB32_CORE_MISC); -        bool ref_locked = (status & PPSLOOP_LOCKED_MASK) && (status & REFPLL_LOCKED_MASK); - -        return sensor_value_t("Ref", ref_locked, "locked", "unlocked"); -    } - -private: -    global_regs::sptr   _global_regs; -}; -}}} - -using namespace uhd::usrp::e300; -e300_sensor_manager::sptr e300_sensor_manager::make_local( -    global_regs::sptr global_regs) -{ -    return sptr(new e300_sensor_local(global_regs)); -} - -#else -using namespace uhd::usrp::e300; -e300_sensor_manager::sptr e300_sensor_manager::make_local( -    global_regs::sptr) -{ -    throw uhd::assertion_error("e300_sensor_manager::make_local() !E300_NATIVE"); -} -#endif diff --git a/host/lib/usrp/e300/e300_sensor_manager.hpp b/host/lib/usrp/e300/e300_sensor_manager.hpp deleted file mode 100644 index 8ed09b1eb..000000000 --- a/host/lib/usrp/e300/e300_sensor_manager.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright 2014-2015 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/utils/noncopyable.hpp> -#include <stdint.h> - -#include <uhd/transport/zero_copy.hpp> -#include <uhd/types/sensors.hpp> -#include <uhd/utils/byteswap.hpp> -#include <uhd/usrp/gps_ctrl.hpp> -#include "e300_global_regs.hpp" - -#ifndef INCLUDED_E300_SENSOR_MANAGER_HPP -#define INCLUDED_E300_SENSOR_MANAGER_HPP - -namespace uhd { namespace usrp { namespace e300 { - -struct sensor_transaction_t { -    uint32_t which; -    union { -        uint32_t value; -        uint32_t value64; -    }; -}; - - - -enum sensor {ZYNQ_TEMP=0, REF_LOCK=4}; - -class e300_sensor_manager : uhd::noncopyable -{ -public: -    typedef boost::shared_ptr<e300_sensor_manager> sptr; - -    virtual ~e300_sensor_manager() {}; - -    virtual uhd::sensor_value_t get_sensor(const std::string &key) = 0; -    virtual std::vector<std::string> get_sensors(void) = 0; - -    virtual uhd::sensor_value_t get_mb_temp(void) = 0; -    virtual uhd::sensor_value_t get_ref_lock(void) = 0; - - -    static sptr make_proxy(uhd::transport::zero_copy_if::sptr xport); -    static sptr make_local(global_regs::sptr global_regs); - -    // Note: This is a hack -    static uint32_t pack_float_in_uint32_t(const float &v) -    { -        const uint32_t *cast = reinterpret_cast<const uint32_t*>(&v); -        return *cast; -    } - -    static float unpack_float_from_uint32_t(const uint32_t &v) -    { -        const float *cast = reinterpret_cast<const float*>(&v); -        return *cast; -    } -}; - - -}}} // namespace - -#endif // INCLUDED_E300_SENSOR_MANAGER_HPP diff --git a/host/lib/usrp/e300/e300_spi.cpp b/host/lib/usrp/e300/e300_spi.cpp deleted file mode 100644 index e0f25c22f..000000000 --- a/host/lib/usrp/e300/e300_spi.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#include <uhd/config.hpp> -#include <uhd/exception.hpp> -#include "e300_spi.hpp" - -#ifdef E300_NATIVE -#include <boost/thread.hpp> -#include <boost/format.hpp> - -#include <fcntl.h> -#include <sys/ioctl.h> -#include <linux/types.h> -#include <linux/spi/spidev.h> - -namespace uhd { namespace usrp { namespace e300 { - -class spidev_impl : public spi -{ -public: - -    spidev_impl(const std::string &device) -                          : _mode(SPI_CPHA), -                            _speed(2000000), -                            _bits(8), -                            _delay(0) -    { -        int ret; -        _fd = open(device.c_str(), O_RDWR); -        if (_fd < 0) -            throw uhd::runtime_error(str(boost::format("Could not open spidev device %s") % device)); - -        ret = ioctl(_fd, SPI_IOC_WR_MODE, &_mode); -        if (ret == -1) -            throw uhd::runtime_error("Could not set spidev mode"); - -        ret = ioctl(_fd, SPI_IOC_RD_MODE, &_mode); -        if (ret == -1) -            throw uhd::runtime_error("Could not get spidev mode"); - -        ret = ioctl(_fd, SPI_IOC_WR_BITS_PER_WORD, &_bits); -        if (ret == -1) -            throw uhd::runtime_error("Could not set spidev bits per word"); - -        ret = ioctl(_fd, SPI_IOC_RD_BITS_PER_WORD, &_bits); -        if (ret == -1) -            throw uhd::runtime_error("Could not get spidev bits per word"); - -        ret = ioctl(_fd, SPI_IOC_WR_MAX_SPEED_HZ, &_speed); -        if (ret == -1) -            throw uhd::runtime_error("Could not set spidev max speed"); - -        ret = ioctl(_fd, SPI_IOC_RD_MAX_SPEED_HZ, &_speed); -        if (ret == -1) -            throw uhd::runtime_error("Could not get spidev max speed"); -    } - -    virtual ~spidev_impl() -    { -        close(_fd); -    } - -    uint32_t transact_spi(int, const uhd::spi_config_t &, -                                 uint32_t data, size_t num_bits, -                                 bool) -    { -        int ret(0); -        struct spi_ioc_transfer tr; - -        uint8_t *tx_data = reinterpret_cast<uint8_t *>(&data); - - -        UHD_ASSERT_THROW(num_bits == 24); -        uint8_t tx[] = {tx_data[2], tx_data[1], tx_data[0]}; - -        uint8_t rx[3]; -        tr.tx_buf = (unsigned long) &tx[0]; -        tr.rx_buf = (unsigned long) &rx[0]; -        tr.len = num_bits >> 3; -        tr.bits_per_word = _bits; -        tr.tx_nbits = 1; -        tr.rx_nbits = 1; -        tr.speed_hz = _speed; -        tr.delay_usecs = _delay; - -        ret = ioctl(_fd, SPI_IOC_MESSAGE(1), &tr); -        if (ret < 1) -            throw uhd::runtime_error("Could not send spidev message"); - -        return rx[2]; -    } - -private: -    int _fd; -    uint8_t _mode; -    uint32_t _speed; -    uint8_t _bits; -    uint16_t _delay; -}; - -spi::sptr spi::make(const std::string &device) -{ -    return spi::sptr(new spidev_impl(device)); -} -}}}; -#else -namespace uhd { namespace usrp { namespace e300 { - -spi::sptr spi::make(const std::string &) -{ -    throw uhd::assertion_error("spi::make() !E300_NATIVE"); -} -}}}; -#endif //E300_NATIVE diff --git a/host/lib/usrp/e300/e300_spi.hpp b/host/lib/usrp/e300/e300_spi.hpp deleted file mode 100644 index 0341ae9c4..000000000 --- a/host/lib/usrp/e300/e300_spi.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifndef INCLUDED_E300_SPI_HPP -#define INCLUDED_E300_SPI_HPP - -#include <uhd/types/serial.hpp> - -namespace uhd { namespace usrp { namespace e300 { - -class spi : public virtual uhd::spi_iface -{ -public: -    typedef boost::shared_ptr<spi> sptr; -    static sptr make(const std::string &device); -}; - -}}}; - -#endif /* INCLUDED_E300_SPI_HPP */ diff --git a/host/lib/usrp/e300/e300_sysfs_hooks.cpp b/host/lib/usrp/e300/e300_sysfs_hooks.cpp deleted file mode 100644 index 81dcff0cb..000000000 --- a/host/lib/usrp/e300/e300_sysfs_hooks.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright 2013-2014 Ettus Research LLC -// Copyright 2018 Ettus Research, a National Instruments Company -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef E300_NATIVE - -#include <cstdio> -#include <cstdlib> -#include <string> -#include <fcntl.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> - -#include <libudev.h> - -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> - -#include <uhd/utils/log.hpp> -#include <uhd/exception.hpp> - -static const std::string E300_AXI_FPGA_SYSFS = "40000000.axi-fpga"; -static const std::string E300_XDEV_SYSFS = "f8007000.ps7-dev-cfg"; - -std::string e300_get_sysfs_attr(const std::string &node, const std::string &attr) -{ -    udev *udev; -    udev_enumerate *enumerate; -    udev_list_entry *devices, *dev_list_entry; -    udev_device *dev; -    std::string retstring; - -    udev = udev_new(); - -    if (!udev) { -        throw uhd::lookup_error("Failed to get udev handle."); -    } - -    enumerate = udev_enumerate_new(udev); -    udev_enumerate_add_match_sysname(enumerate, node.c_str()); -    udev_enumerate_scan_devices(enumerate); -    devices = udev_enumerate_get_list_entry(enumerate); - -    udev_list_entry_foreach(dev_list_entry, devices) -    { -        const char *path; - -        path = udev_list_entry_get_name(dev_list_entry); -        dev = udev_device_new_from_syspath(udev, path); - -       retstring = udev_device_get_sysattr_value(dev, attr.c_str()); - -       udev_device_unref(dev); - -       if (retstring.size()) -           break; -    } - -    udev_enumerate_unref(enumerate); -    udev_unref(udev); - -    return retstring; -} - -static bool e300_fpga_loaded_successfully(void) -{ -    return boost::lexical_cast<bool>(e300_get_sysfs_attr(E300_XDEV_SYSFS, "prog_done")); -} - -#include "e300_fifo_config.hpp" -#include <uhd/exception.hpp> - -e300_fifo_config_t e300_read_sysfs(void) -{ - -    if (not e300_fpga_loaded_successfully()) -    { -        throw uhd::runtime_error("E300 FPGA load failed!"); -    } - -    e300_fifo_config_t config; - -    config.buff_length  = std::stoul( -        e300_get_sysfs_attr(E300_AXI_FPGA_SYSFS, "buffer_length")); -    config.ctrl_length = std::stoul( -        e300_get_sysfs_attr(E300_AXI_FPGA_SYSFS, "control_length")); -    config.phys_addr = std::stoul( -        e300_get_sysfs_attr(E300_AXI_FPGA_SYSFS, "phys_addr")); - -    return config; -} - -#else //E300_NATIVE - -#include "e300_fifo_config.hpp" -#include <uhd/exception.hpp> - -e300_fifo_config_t e300_read_sysfs(void) -{ -    throw uhd::assertion_error("e300_read_sysfs() !E300_NATIVE"); -} - -std::string e300_get_sysfs_attr(const std::string &, const std::string &) -{ -    throw uhd::assertion_error("e300_sysfs_attr() !E300_NATIVE"); -} - -#endif //E300_NATIVE diff --git a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp b/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp deleted file mode 100644 index 787faf6df..000000000 --- a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.cpp +++ /dev/null @@ -1,770 +0,0 @@ -// -// Copyright 2015-2016 Ettus Research -// -// 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 "e3xx_radio_ctrl_impl.hpp" -#include "e300_defaults.hpp" -#include "e300_regs.hpp" -#include <boost/make_shared.hpp> -#include <uhd/usrp/dboard_iface.hpp> -#include <uhd/rfnoc/node_ctrl_base.hpp> -#include <uhd/utils/log.hpp> -#include <boost/algorithm/string.hpp> -#include <boost/make_shared.hpp> - -using namespace uhd; -using namespace uhd::rfnoc; -using namespace uhd::usrp::e300; -using uhd::usrp::dboard_iface; - -//! mapping of frontend to radio perif index -static const size_t FE0 = 1; -static const size_t FE1 = 0; - -/**************************************************************************** - * Structors - ***************************************************************************/ -UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(e3xx_radio_ctrl) -{ -    UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::ctor() " << std::endl; - -    //////////////////////////////////////////////////////////////////// -    // Set up peripherals -    //////////////////////////////////////////////////////////////////// -    for (size_t i = 0; i < _get_num_radios(); i++) { -        if (i == 0) { -            _spi = spi_core_3000::make(_get_ctrl(i), regs::sr_addr(regs::SPI), regs::RB_SPI); -            _spi->set_divider(6); -        } -        _e3xx_perifs[i].atr = usrp::gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::GPIO)); -        _e3xx_perifs[i].leds = usrp::gpio_atr::gpio_atr_3000::make_write_only(_get_ctrl(i), regs::sr_addr(regs::LEDS)); -        _e3xx_perifs[i].leds->set_atr_mode(usrp::gpio_atr::MODE_ATR, usrp::gpio_atr::gpio_atr_3000::MASK_SET_ALL); -    } - -    //////////////////////////////////////////////////////////////////// -    // Time source -    //////////////////////////////////////////////////////////////////// -    _tree->create<std::string>("time_source/value") -        .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::_update_time_source, this, _1)) -        .set(DEFAULT_TIME_SRC); -#ifdef E300_GPSD -    static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external")("gpsdo"); -#else -    static const std::vector<std::string> time_sources = boost::assign::list_of("none")("internal")("external"); -#endif -    _tree->create<std::vector<std::string> >("time_source/options").set(time_sources); - -    //////////////////////////////////////////////////////////////////// -    // create RF frontend interfacing -    //////////////////////////////////////////////////////////////////// -    { -        const fs_path codec_path = fs_path("rx_codecs") / "A"; -        _tree->create<std::string>(codec_path / "name").set("E3x0 RX dual ADC"); -        _tree->create<int>(codec_path / "gains"); //empty cuz gains are in frontend -    } -    { -        const fs_path codec_path = fs_path("tx_codecs") / "A"; -        _tree->create<std::string>(codec_path / "name").set("E3x0 TX dual DAC"); -        _tree->create<int>(codec_path / "gains"); //empty cuz gains are in frontend -    } - -    //////////////////////////////////////////////////////////////////// -    // internal gpios -    //////////////////////////////////////////////////////////////////// -    UHD_RFNOC_BLOCK_TRACE() << "  Creating internal GPIOs..." << std::endl; - -    usrp::gpio_atr::gpio_atr_3000::sptr fp_gpio = usrp::gpio_atr::gpio_atr_3000::make( -        get_ctrl_iface(0), -        regs::sr_addr(regs::FP_GPIO), -        regs::RB_FP_GPIO -    ); -    for (const auto& attr : usrp::gpio_atr::gpio_attr_map) { -        switch (attr.first) { -        case usrp::gpio_atr::GPIO_SRC: -            _tree->create<std::vector<std::string>>(fs_path("gpio") / "INT0" / attr.second) -                 .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) -                 .add_coerced_subscriber([this](const std::vector<std::string>&){ -                    throw uhd::runtime_error("This device does not support setting the GPIO_SRC attribute."); -                 }); -            break; -        case usrp::gpio_atr::GPIO_CTRL: -        case usrp::gpio_atr::GPIO_DDR: -            _tree->create<std::vector<std::string>>(fs_path("gpio") / "INT0" / attr.second) -                 .set(std::vector<std::string>(32, usrp::gpio_atr::default_attr_value_map.at(attr.first))) -                 .add_coerced_subscriber([this, fp_gpio, 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; -                    } -                    fp_gpio->set_gpio_attr(attr.first, val); -                 }); -            break; -        case usrp::gpio_atr::GPIO_READBACK: -            _tree->create<uint8_t>(fs_path("gpio") / "INT0" / "READBACK") -                .set_publisher([this, fp_gpio](){ -                    return fp_gpio->read_gpio(); -                 }); -            break; -        default: -            _tree->create<uint32_t>(fs_path("gpio") / "INT0" / attr.second) -                 .set(0) -                 .add_coerced_subscriber([this, fp_gpio, attr](const uint32_t val){ -                     fp_gpio->set_gpio_attr(attr.first, val); -                 }); -            } -    } - -    //////////////////////////////////////////////////////////////////// -    // Tick rate -    //////////////////////////////////////////////////////////////////// -    UHD_RFNOC_BLOCK_TRACE() << "  Setting tick rate..." << std::endl; -    _tree->access<double>("tick_rate") -        .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1)) -        .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_rate, this)) -    ; -} - -e3xx_radio_ctrl_impl::~e3xx_radio_ctrl_impl() -{ -    const std::string _radio_slot = "A"; -    // Tear down our part of the tree: -    _tree->remove(fs_path("rx_codecs" / _radio_slot)); -    _tree->remove(fs_path("tx_codecs" / _radio_slot)); -    for (size_t i = 0; i < _get_num_radios(); i++) { -        if (_tree->exists(fs_path("tx_dsps") / i)) { -            _tree->remove(fs_path("tx_dsps") / i); -        } -        if (_tree->exists(fs_path("rx_dsps") / i)) { -            _tree->remove(fs_path("rx_dsps") / i); -        } -    } -    for (const auto attr : usrp::gpio_atr::gpio_attr_map) { -        const auto gpio_fs_path = fs_path("gpio") / "INT0" / attr.second; -        if (_tree->exists(gpio_fs_path)) { -            _tree->remove(gpio_fs_path); -        } -    } -} - -/**************************************************************************** - * API calls - ***************************************************************************/ -double e3xx_radio_ctrl_impl::set_rate(double rate) -{ -    //UHD_LOGGER_DEBUG("E300") << "Setting SPI divider to " << ceil(rate/AD9361_SPI_RATE) << "\n"; -    //_spi->set_divider(ceil(rate/AD9361_SPI_RATE)); // ceil() to prevent less than 1 rounding to 0 -    UHD_LOGGER_DEBUG("E300") << "Asking for clock rate " << rate/1e6 << " MHz\n"; -    double actual_tick_rate = _codec_ctrl->set_clock_rate(rate); -    UHD_LOGGER_DEBUG("E300") << "Actually got clock rate " << actual_tick_rate/1e6 << " MHz\n"; - -    actual_tick_rate = radio_ctrl_impl::set_rate(actual_tick_rate); - -    if (not check_radio_config()) { -        throw std::runtime_error(str( -            boost::format("[%s]: Invalid radio configuration.") -            % unique_id() -        )); -    } - -    return actual_tick_rate; -} - -/*! Select TX antenna \p for channel \p chan. - */ -void e3xx_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    if (ant != "TX/RX") -        throw uhd::value_error("Unknown TX antenna option: " + ant); - -    radio_ctrl_impl::set_tx_antenna(ant, chan); -} - -/*! Select RX antenna \p for channel \p chan. - */ -void e3xx_radio_ctrl_impl::set_rx_antenna(const std::string &ant, const size_t chan) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    if (ant != "TX/RX" and ant != "RX2") -        throw uhd::value_error("Unknown RX antenna option: " + ant); - -    radio_ctrl_impl::set_rx_antenna(ant, chan); -    this->_update_atrs(); -    this->_update_atr_leds(_e3xx_perifs[chan].leds, ant); -} - -double e3xx_radio_ctrl_impl::set_tx_frequency(const double freq, const size_t) -{ -    return _tree->access<double>(fs_path("dboards/A/tx_frontends/A/freq/value")).set(freq).get(); -} - -double e3xx_radio_ctrl_impl::set_rx_frequency(const double freq, const size_t) -{ -    return _tree->access<double>(fs_path("dboards/A/rx_frontends/A/freq/value")).set(freq).get(); -} - -double e3xx_radio_ctrl_impl::set_tx_gain(const double gain, const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    double new_gain = _tree->access<double>(fs_path("dboards/A/tx_frontends/" + fe_side + "/gains/PGA/value")).set(gain).get(); -    return radio_ctrl_impl::set_tx_gain(new_gain, chan); -} - -double e3xx_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    double new_gain = _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/gains/PGA/value")).set(gain).get(); -    return radio_ctrl_impl::set_rx_gain(new_gain, chan); -} - -double e3xx_radio_ctrl_impl::set_rx_bandwidth(const double bandwidth, const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    double new_bw = _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/bandwidth/value")).set(bandwidth).get(); -    return radio_ctrl_impl::set_rx_bandwidth(new_bw, chan); -} - -double e3xx_radio_ctrl_impl::get_tx_gain(const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    return _tree->access<double>(fs_path("dboards/A/tx_frontends/" + fe_side + "/gains/PGA/value")).get(); -} - -double e3xx_radio_ctrl_impl::get_rx_gain(const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    return _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/gains/PGA/value")).get(); -} - -double e3xx_radio_ctrl_impl::get_rx_bandwidth(const size_t chan) -{ -    const std::string fe_side = (chan == 0) ? "A" : "B"; -    return _tree->access<double>(fs_path("dboards/A/rx_frontends/" + fe_side + "/bandwidth/value")).get(); -} - -std::vector<std::string> e3xx_radio_ctrl_impl::get_gpio_banks() const -{ -    std::vector<std::string> banks = boost::assign::list_of("INT0"); -    return banks; -} - -void e3xx_radio_ctrl_impl::set_gpio_attr( -        const std::string &bank, -        const std::string &attr, -        const uint32_t value, -        const uint32_t mask -) { -    if (bank == "INT0") { -        const uint32_t current = _tree->access<uint32_t>(fs_path("gpio") / bank / attr).get(); -        const uint32_t new_value = (current & ~mask) | (value & mask); -        _tree->access<uint32_t>(fs_path("gpio") / bank / attr).set(new_value); -        return; -    } -} - -uint32_t e3xx_radio_ctrl_impl::get_gpio_attr( -        const std::string &bank, -        const std::string &attr -) { -    if (bank == "INT0") { -        return uint32_t(_tree->access<uint64_t>(fs_path("gpio") / bank / attr).get()); -    } -    return 0; -} - -size_t e3xx_radio_ctrl_impl::get_chan_from_dboard_fe(const std::string &fe, const direction_t) -{ -    return (fe == "A") ? 0 : 1; -} - -std::string e3xx_radio_ctrl_impl::get_dboard_fe_from_chan(const size_t chan, const direction_t) -{ -    return (chan == 0) ? "A" : "B"; -} - -/**************************************************************************** - * Radio control and setup - ***************************************************************************/ -void e3xx_radio_ctrl_impl::setup_radio(uhd::usrp::ad9361_ctrl::sptr safe_codec_ctrl) -{ -    { -        std::lock_guard<std::mutex> lock(_mutex); -        if (_codec_ctrl) { -            throw std::runtime_error("Attempting to set up radio twice!"); -        } -    } - -    //////////////////////////////////////////////////////////////////// -    // Create timed interface -    //////////////////////////////////////////////////////////////////// -    _codec_ctrl = safe_codec_ctrl; -    _codec_mgr = uhd::usrp::ad936x_manager::make(_codec_ctrl, _get_num_radios()); - -    //////////////////////////////////////////////////////////////////// -    // setup radios -    //////////////////////////////////////////////////////////////////// -    for (size_t chan = 0; chan < _get_num_radios(); chan++) { -        _setup_radio_channel(chan); -    } -    // Loopback test -    for (size_t chan = 0; chan < _get_num_radios(); chan++) { -        _codec_mgr->loopback_self_test( -            [this, chan](const uint32_t value){ -                this->sr_write(regs::CODEC_IDLE, value, chan); -            }, -            [this, chan](){ -                return this->user_reg_read64(regs::RB_CODEC_READBACK, chan); -            } -        ); -    } - -    this->_update_enables(); -} - -void e3xx_radio_ctrl_impl::_setup_radio_channel(const size_t chan) -{ -    const fs_path rx_dsp_path = fs_path("rx_dsps") / chan; -    _tree->create<stream_cmd_t>(rx_dsp_path / "stream_cmd") -        .add_coerced_subscriber(boost::bind(&radio_ctrl_impl::issue_stream_cmd, this, _1, chan)); - -    //////////////////////////////////////////////////////////////////// -    // add some dummy nodes on the prop tree (FIXME remove these) -    //////////////////////////////////////////////////////////////////// -    const fs_path tx_dsp_path = fs_path("tx_dsps") / chan; -    _tree->create<double>(tx_dsp_path / "freq/value").set(0.0); -    _tree->create<meta_range_t>(tx_dsp_path / "freq/range").set(meta_range_t(0.0, 0.0, 0.0)); -    _tree->create<double>(rx_dsp_path / "freq/value").set(0.0); -    _tree->create<meta_range_t>(rx_dsp_path / "freq/range").set(meta_range_t(0.0, 0.0, 0.0)); -    _tree->create<double>(tx_dsp_path / "rate/value") -        .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1)) -        .set_publisher(boost::bind(&radio_ctrl_impl::get_rate, this)) -    ; -    _tree->create<double>(rx_dsp_path / "rate/value") -        .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rate, this, _1)) -        .set_publisher(boost::bind(&radio_ctrl_impl::get_rate, this)) -    ; - -    //////////////////////////////////////////////////////////////////// -    // create RF frontend interfacing -    //////////////////////////////////////////////////////////////////// -    static const std::vector<direction_t> dirs = boost::assign::list_of(RX_DIRECTION)(TX_DIRECTION); -    BOOST_FOREACH(direction_t dir, dirs) { -        const std::string x = (dir == RX_DIRECTION) ? "rx" : "tx"; -        const std::string key = boost::to_upper_copy(x) + std::string(((chan == FE0)? "1" : "2")); -        const fs_path rf_fe_path -            = fs_path("dboards") / "A" / (x + "_frontends") / ((chan == 0) ? "A" : "B"); - -        // This will connect all the AD936x-specific items -        _codec_mgr->populate_frontend_subtree( -            _tree->subtree(rf_fe_path), key, dir -        ); - -        // This will connect all the e3xx_radio_ctrl-specific items -        _tree->create<sensor_value_t>(rf_fe_path / "sensors" / "lo_locked") -            .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::_get_fe_pll_lock, this, dir == TX_DIRECTION)) -        ; -        const double freq = _tree->access<double>(rf_fe_path / "freq" / "value") -            .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::_update_fe_lo_freq, this, key, _1)).get() -        ; -        // Set frequency in parent (to be used to update ATR values later) -        if (dir == RX_DIRECTION) { -            radio_ctrl_impl::set_rx_frequency(freq, chan); -        } else { -            radio_ctrl_impl::set_tx_frequency(freq, chan); -        } - -        // Antenna Setup -        if (dir == RX_DIRECTION) { -            static const std::vector<std::string> ants = boost::assign::list_of("TX/RX")("RX2"); -            _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options").set(ants); -            _tree->create<std::string>(rf_fe_path / "antenna" / "value") -                .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_rx_antenna, this, _1, chan)) -                .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_rx_antenna, this, chan)); -            // Set default in parent (to be used to update ATR values later) -            radio_ctrl_impl::set_rx_antenna("RX2", chan); -            // Set up LEDs for default antenna -            _update_atr_leds(_e3xx_perifs[chan].leds, "RX2"); -        } -        else if (dir == TX_DIRECTION) { -            static const std::vector<std::string> ants(1, "TX/RX"); -            _tree->create<std::vector<std::string> >(rf_fe_path / "antenna" / "options").set(ants); -            _tree->create<std::string>(rf_fe_path / "antenna" / "value") -            .add_coerced_subscriber(boost::bind(&e3xx_radio_ctrl_impl::set_tx_antenna, this, _1, chan)) -            .set_publisher(boost::bind(&e3xx_radio_ctrl_impl::get_tx_antenna, this, chan)) -            .set("TX/RX"); -        } -    } -} - -void e3xx_radio_ctrl_impl::_reset_radio(void) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    _misc.radio_rst = 1; -    _update_gpio_state(); -    boost::this_thread::sleep(boost::posix_time::milliseconds(10)); -    _misc.radio_rst = 0; -    _update_gpio_state(); -    boost::this_thread::sleep(boost::posix_time::milliseconds(10)); -} - -/**************************************************************************** - * Helpers - ***************************************************************************/ -bool e3xx_radio_ctrl_impl::check_radio_config() -{ -    const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); -    const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); -    _enforce_tick_rate_limits( -        std::max(num_rx, num_tx), -        get_tick_rate() -    ); - -    this->_update_enables(); -    return true; -} - -void e3xx_radio_ctrl_impl::_enforce_tick_rate_limits( -        const size_t chan_count, -        const double tick_rate -) { -    const size_t max_chans = 2; -    if (chan_count > max_chans) { -        throw uhd::value_error(boost::str( -            boost::format("cannot not setup %d channels per direction (maximum is %d)") -                % chan_count -                % max_chans -        )); -    } else { -        const double max_tick_rate = uhd::usrp::ad9361_device_t::AD9361_MAX_CLOCK_RATE / ((chan_count <= 1) ? 1 : 2); -        if (tick_rate - max_tick_rate >= 1.0) -        { -            throw uhd::value_error(boost::str( -                boost::format("current master clock rate (%.6f MHz) exceeds maximum possible master clock rate (%.6f MHz) when using %d channels") -                    % (tick_rate/1e6) -                    % (max_tick_rate/1e6) -                    % chan_count -            )); -        } -        // TODO minimum rate check -    } -} - -/**************************************************************************** - * Peripheral controls - ***************************************************************************/ -void e3xx_radio_ctrl_impl::_update_fe_lo_freq(const std::string &fe, const double freq) -{ -    if (fe[0] == 'R') { -        for (size_t i = 0; i < _get_num_radios(); i++) { -            radio_ctrl_impl::set_rx_frequency(freq, i); -        } -    } -    if (fe[0] == 'T') { -        for (size_t i = 0; i < _get_num_radios(); i++) { -            radio_ctrl_impl::set_tx_frequency(freq, i); -        } -    } -    this->_update_atrs(); -} - -void e3xx_radio_ctrl_impl::_update_atrs(void) -{ -    for (size_t instance = 0; instance < _get_num_radios(); instance++) -    { -        // if we're not ready, no point ... -        if (not _e3xx_perifs[instance].atr) -            return; - -        const bool rx_ant_rx2  = get_rx_antenna(instance) == "RX2"; -        const double rx_freq = get_rx_frequency(instance); -        const double tx_freq = get_tx_frequency(instance); -        const bool rx_low_band = rx_freq < 2.6e9; -        const bool tx_low_band = tx_freq < 2940.0e6; - -        // VCRX -        uint32_t vcrx_v1_rxing = 1; -        uint32_t vcrx_v2_rxing = 0; -        uint32_t vcrx_v1_txing = 1; -        uint32_t vcrx_v2_txing = 0; - -        if (rx_low_band) { -            vcrx_v1_rxing = rx_ant_rx2 ? 0 : 1; -            vcrx_v2_rxing = rx_ant_rx2 ? 1 : 0; -            vcrx_v1_txing = 0; -            vcrx_v2_txing = 1; -        } else { -            vcrx_v1_rxing = rx_ant_rx2 ? 1 : 0; -            vcrx_v2_rxing = rx_ant_rx2 ? 0 : 1; -            vcrx_v1_txing = 1; -            vcrx_v2_txing = 0; -        } - -        // VCTX -        uint32_t vctxrx_v1_rxing = 0; -        uint32_t vctxrx_v2_rxing = 1; -        uint32_t vctxrx_v1_txing = 0; -        uint32_t vctxrx_v2_txing = 1; - -        if (tx_low_band) { -            vctxrx_v1_rxing = rx_ant_rx2 ? 1 : 0; -            vctxrx_v2_rxing = rx_ant_rx2 ? 0 : 1; -            vctxrx_v1_txing = 1; -            vctxrx_v2_txing = 0; -        } else { -            vctxrx_v1_rxing = rx_ant_rx2 ? 1 : 0; -            vctxrx_v2_rxing = rx_ant_rx2 ? 0 : 1; -            vctxrx_v1_txing = 1; -            vctxrx_v2_txing = 1; -        } - -        //swapped for routing reasons, reswap it here -        if (instance == 1) { -            std::swap(vctxrx_v1_rxing, vctxrx_v2_rxing); -            std::swap(vctxrx_v1_txing, vctxrx_v2_txing); -        } - -        uint32_t tx_enable_a = (!tx_low_band) ? 1 : 0; -        uint32_t tx_enable_b = (tx_low_band) ? 1 : 0; - -        /* Set RX / TX band selects */ -        uint32_t rx_band_select_a = 0; -        uint32_t rx_band_select_b = 0; -        uint32_t rx_band_select_c = 0; -        uint32_t tx_band_select = 0; - -        if (instance == 0) { -            // RX -            if (rx_freq < 450e6) { -                rx_band_select_a = 5; // 3'b101 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 1; // 2'b01 -            } else if (rx_freq < 700e6) { -                rx_band_select_a = 3; // 3'b011 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 3; // 2'b11 -            } else if (rx_freq < 1200e6) { -                rx_band_select_a = 1; // 3'b001 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 2; // 2'b10 -            } else if (rx_freq < 1800e6) { -                rx_band_select_a = 0; // 3'b000 -                rx_band_select_b = 1; // 2'b01 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else if (rx_freq < 2350e6){ -                rx_band_select_a = 2; // 3'b010 -                rx_band_select_b = 3; // 2'b11 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else if (rx_freq < 2600e6){ -                rx_band_select_a = 4; // 3'b100 -                rx_band_select_b = 2; // 2'b10 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else { // >= 2600e6 -                rx_band_select_a = 5; // 3'bXX -- Don't care -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 1; // 2'bXX -- Don't care -            } -        } else if (instance == 1) { -            if (rx_freq < 450e6) { -                rx_band_select_a = 4; // 3'b100 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 2; // 2'b10 -            } else if (rx_freq < 700e6) { -                rx_band_select_a = 2; // 3'b010 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 3; // 2'b11 -            } else if (rx_freq < 1200e6) { -                rx_band_select_a = 0; // 3'b000 -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 1; // 2'b01 -            } else if (rx_freq < 1800e6) { -                rx_band_select_a = 1; // 3'b001 -                rx_band_select_b = 2; // 2'b10 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else if (rx_freq < 2350e6){ -                rx_band_select_a = 3; // 3'b011 -                rx_band_select_b = 3; // 2'b11 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else if (rx_freq < 2600e6){ -                rx_band_select_a = 5; // 3'b101 -                rx_band_select_b = 1; // 2'b01 -                rx_band_select_c = 0; // 2'bXX -- Don't care -            } else { // >= 2600e6 -                rx_band_select_a = 5; // 3'bXX -- Don't care -                rx_band_select_b = 0; // 2'bXX -- Don't care -                rx_band_select_c = 1; // 2'bXX -- Don't care -            } -        } else { -            UHD_THROW_INVALID_CODE_PATH(); -        } - -        // TX band selects are the same for both radio frontends -        if (tx_freq < 117.7e6) -            tx_band_select = 7; // 3'b111 -        else if (tx_freq < 178.2e6) -            tx_band_select = 6; // 3'b110 -        else if (tx_freq < 284.3e6) -            tx_band_select = 5; // 3'b101 -        else if (tx_freq < 453.7e6) -            tx_band_select = 4; // 3'b100 -        else if (tx_freq < 723.8e6) -            tx_band_select = 3; // 3'b011 -        else if (tx_freq < 1154.9e6) -            tx_band_select = 2; // 3'b010 -        else if (tx_freq < 1842.6e6) -            tx_band_select = 1; // 3'b001 -        else if (tx_freq < 2940.0e6) -            tx_band_select = 0; // 3'b000 -        else // > 2940.0e6 -            tx_band_select = 7; // 3'bXXX -- Don't care, set to lowest band - -        const uint32_t rx_selects = 0 -            | (vcrx_v1_rxing << VCRX_V1) -            | (vcrx_v2_rxing << VCRX_V2) -            | (vctxrx_v1_rxing << VCTXRX_V1) -            | (vctxrx_v2_rxing << VCTXRX_V2) -        ; -        const uint32_t tx_selects = 0 -            | (vcrx_v1_txing << VCRX_V1) -            | (vcrx_v2_txing << VCRX_V2) -            | (vctxrx_v1_txing << VCTXRX_V1) -            | (vctxrx_v2_txing << VCTXRX_V2) -        ; -        const uint32_t tx_enables = 0 -            | (tx_enable_a << TX_ENABLEA) -            | (tx_enable_b << TX_ENABLEB) -        ; -        const uint32_t rxtx_band_selects = 0 -            | (rx_band_select_a << RX_BANDSEL) -            | (rx_band_select_b << RXB_BANDSEL) -            | (rx_band_select_c << RXC_BANDSEL) -            | (tx_band_select << TX_BANDSEL) -        ; - -        // Form register values; -        uint32_t oo_reg = rx_selects | rxtx_band_selects; -        uint32_t rx_reg = rx_selects | rxtx_band_selects; -        uint32_t tx_reg = tx_selects | tx_enables | rxtx_band_selects; -        uint32_t fd_reg = tx_selects | tx_enables | rxtx_band_selects; //tx selects dominate in fd mode - -        //add tx enables based on fe enable -        tx_reg |= tx_enables; -        fd_reg |= tx_enables; - -        usrp::gpio_atr::gpio_atr_3000::sptr atr = _e3xx_perifs[instance].atr; -        atr->set_atr_reg(usrp::gpio_atr::ATR_REG_IDLE, oo_reg); -        atr->set_atr_reg(usrp::gpio_atr::ATR_REG_RX_ONLY, rx_reg); -        atr->set_atr_reg(usrp::gpio_atr::ATR_REG_TX_ONLY, tx_reg); -        atr->set_atr_reg(usrp::gpio_atr::ATR_REG_FULL_DUPLEX, fd_reg); -    } -} - -void e3xx_radio_ctrl_impl::_update_atr_leds(usrp::gpio_atr::gpio_atr_3000::sptr leds, const std::string &rx_ant) -{ -    const bool is_txrx = (rx_ant == "TX/RX"); -    const int rx_led = (1 << 2); -    const int tx_led = (1 << 1); -    const int txrx_led = (1 << 0); -    using namespace uhd::usrp::gpio_atr; -    leds->set_atr_reg(ATR_REG_IDLE, 0); -    leds->set_atr_reg(ATR_REG_RX_ONLY, is_txrx ? txrx_led : rx_led); -    leds->set_atr_reg(ATR_REG_TX_ONLY, tx_led); -    leds->set_atr_reg(ATR_REG_FULL_DUPLEX, rx_led | tx_led); -} - -void e3xx_radio_ctrl_impl::_update_gpio_state(void) -{ -    UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::_update_gpio_state() " << std::endl; -    uint32_t misc_reg = 0 -        | (_misc.pps_sel      << gpio_t::PPS_SEL) -        | (_misc.mimo         << gpio_t::MIMO) -        | (_misc.radio_rst    << gpio_t::RADIO_RST); -    _tree->access<uint32_t>("global_regs/misc").set(misc_reg); -} - -void e3xx_radio_ctrl_impl::_update_enables(void) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    UHD_RFNOC_BLOCK_TRACE() << "e3xx_radio_ctrl_impl::_update_enables() " << std::endl; -    if (not _codec_ctrl) { -        UHD_LOGGER_WARNING("E300") << "Attempting to access CODEC controls before setting up the radios." << std::endl; -        return; -    } - -    const size_t num_rx = _is_streamer_active(RX_DIRECTION, FE0) + _is_streamer_active(RX_DIRECTION, FE1); -    const size_t num_tx = _is_streamer_active(TX_DIRECTION, FE0) + _is_streamer_active(TX_DIRECTION, FE1); - -    const bool mimo = (num_rx == 2) or (num_tx == 2); - -    // This currently doesn't work with GNU Radio, so leave it uncommented -    //if ((num_tx + num_rx) == 3) -    //    throw uhd::runtime_error("e300: 2 RX 1 TX and 1 RX 2 TX configurations not possible"); - -    //setup the active chains in the codec -    if ((num_rx + num_tx) == 0) { -        // Ensure at least one RX chain is enabled so AD9361 outputs a sample clock -        _codec_ctrl->set_active_chains(false, false, true, false); -    } else { -        _codec_ctrl->set_active_chains( -                _is_streamer_active(TX_DIRECTION, FE0), -                _is_streamer_active(TX_DIRECTION, FE1), -                _is_streamer_active(RX_DIRECTION, FE0), -                _is_streamer_active(RX_DIRECTION, FE1) -        ); -    } - -    // Set radio data direction register cleared due to reset -    for (size_t instance = 0; instance < _get_num_radios(); instance++) -    { -        _e3xx_perifs[instance].atr->set_gpio_ddr(usrp::gpio_atr::DDR_OUTPUT, 0xFFFFFFFF); -    } - -    //figure out if mimo is enabled based on new state -    _misc.mimo = (mimo) ? 1 : 0; -    _update_gpio_state(); - -    //atrs change based on enables -    _update_atrs(); -} - -void e3xx_radio_ctrl_impl::_update_time_source(const std::string &source) -{ -    std::lock_guard<std::mutex> lock(_mutex); -    UHD_LOGGER_DEBUG("E300") << boost::format("Setting time source to %s") % source << std::endl; -    if (source == "none" or source == "internal") { -        _misc.pps_sel = global_regs::PPS_INT; -#ifdef E300_GPSD -    } else if (source == "gpsdo") { -        _misc.pps_sel = global_regs::PPS_GPS; -#endif -    } else if (source == "external") { -        _misc.pps_sel = global_regs::PPS_EXT; -    } else { -        throw uhd::key_error("update_time_source: unknown source: " + source); -    } -    _update_gpio_state(); -} - -uhd::sensor_value_t e3xx_radio_ctrl_impl::_get_fe_pll_lock(const bool is_tx) -{ -    const uint32_t st = _tree->access<uint32_t>("global_regs/pll").get(); -    const bool locked = is_tx ? ((st & 0x1) > 0) : ((st & 0x2) > 0); -    return sensor_value_t("LO", locked, "locked", "unlocked"); -} - -/**************************************************************************** - * Register block - ***************************************************************************/ -UHD_RFNOC_BLOCK_REGISTER(e3xx_radio_ctrl, "E3XXRadio"); diff --git a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.hpp b/host/lib/usrp/e300/e3xx_radio_ctrl_impl.hpp deleted file mode 100644 index 390b0929c..000000000 --- a/host/lib/usrp/e300/e3xx_radio_ctrl_impl.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright 2015-2016 Ettus Research -// -// 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_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP -#define INCLUDED_LIBUHD_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP - -#include "e300_global_regs.hpp" -#include <uhdlib/usrp/cores/spi_core_3000.hpp> -#include <uhdlib/usrp/common/ad9361_ctrl.hpp> -#include <uhdlib/usrp/common/ad936x_manager.hpp> -#include <uhdlib/rfnoc/radio_ctrl_impl.hpp> -#include <uhd/usrp/gpio_defs.hpp> - -namespace uhd { -    namespace rfnoc { - -/*! \brief Provide access to an E3XX radio. - */ -class e3xx_radio_ctrl_impl : public radio_ctrl_impl -{ -public: -    /************************************************************************ -     * Structors -     ***********************************************************************/ -    UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR_DECL(e3xx_radio_ctrl) -    virtual ~e3xx_radio_ctrl_impl(); - -    /************************************************************************ -     * API calls -     ***********************************************************************/ -    double set_rate(double rate); -    void set_tx_antenna(const std::string &ant, const size_t chan); -    void set_rx_antenna(const std::string &ant, const size_t chan); - -    double set_tx_frequency(const double freq, const size_t chan); -    double set_rx_frequency(const double freq, const size_t chan); - -    double set_tx_gain(const double gain, const size_t chan); -    double set_rx_gain(const double gain, const size_t chan); -    double set_rx_bandwidth(const double bandwidth, const size_t chan); - -    double get_tx_gain(const size_t chan); -    double get_rx_gain(const size_t chan); -    double get_rx_bandwidth(const size_t chan); - -    std::vector<std::string> get_gpio_banks() const; -    void set_gpio_attr(const std::string &bank, const std::string &attr, const uint32_t value, const uint32_t mask); -    uint32_t get_gpio_attr(const std::string &bank, const std::string &attr); - -    size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t); -    std::string get_dboard_fe_from_chan(const size_t chan, const direction_t); - -    /************************************************************************ -     * RFIC setup and control -     ***********************************************************************/ -    /*! Set up the radio. No API calls may be made before this one. -     */ -    void setup_radio(uhd::usrp::ad9361_ctrl::sptr safe_codec_ctrl); - -private: -    void _setup_radio_channel(const size_t chan); -    void _reset_radio(void); - -protected: -    /************************************************************************ -     * Helpers -     ***********************************************************************/ -    virtual bool check_radio_config(); -    void _enforce_tick_rate_limits(const size_t chans, const double tick_rate); - -private: -    /************************************************************************ -     * Peripheral controls -     ***********************************************************************/ -    void _update_fe_lo_freq(const std::string &fe, const double freq); -    void _update_atrs(void); -    void _update_atr_leds(uhd::usrp::gpio_atr::gpio_atr_3000::sptr leds, const std::string &rx_ant); - -    void _update_gpio_state(void); -    void _update_enables(void); - -    void _update_time_source(const std::string &source); - -    // get frontend lock sensor -    uhd::sensor_value_t _get_fe_pll_lock(const bool is_tx); - -    /************************************************************************ -     * Internal GPIO control -     ***********************************************************************/ -    struct gpio_t -    { -        gpio_t() : pps_sel(uhd::usrp::e300::global_regs::PPS_INT), -            mimo(0), radio_rst(0), tx_bandsels(0), -            rx_bandsel_a(0), rx_bandsel_b(0), rx_bandsel_c(0) -        {} - -        uint32_t pps_sel; -        uint32_t mimo; -        uint32_t radio_rst; - -        uint32_t tx_bandsels; -        uint32_t rx_bandsel_a; -        uint32_t rx_bandsel_b; -        uint32_t rx_bandsel_c; - -        static const size_t PPS_SEL     = 0; -        static const size_t MIMO        = 2; -        static const size_t RADIO_RST   = 3; -        static const size_t TX_BANDSEL  = 4; -        static const size_t RX_BANDSELA = 7; -        static const size_t RX_BANDSELB = 13; -        static const size_t RX_BANDSELC = 17; -    }; -    uint8_t _get_internal_gpio(uhd::usrp::gpio_atr::gpio_atr_3000::sptr); - -private: // members -    struct e3xx_perifs_t -    { -        usrp::gpio_atr::gpio_atr_3000::sptr      atr; -        uhd::usrp::gpio_atr::gpio_atr_3000::sptr leds; -    }; -    //! SPI to talk to the AD936x -    spi_core_3000::sptr                    _spi; -    //! One ATR per channel -    std::map<size_t, e3xx_perifs_t>        _e3xx_perifs; -    //! AD936x controls -    uhd::usrp::ad9361_ctrl::sptr           _codec_ctrl; -    uhd::usrp::ad936x_manager::sptr        _codec_mgr; -    gpio_t                                 _misc; - -}; /* class radio_ctrl_impl */ - -}} /* namespace uhd::rfnoc */ - -#endif /* INCLUDED_LIBUHD_RFNOC_E3XX_RADIO_CTRL_IMPL_HPP */ diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index 4e8d8e5f0..58eb842e1 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -18,13 +18,6 @@ set(util_runtime_sources      uhd_cal_tx_iq_balance.cpp  ) -find_package(UDev) -if(ENABLE_E300 AND NOT E300_FORCE_NETWORK) -    if(UDEV_FOUND) -        list(APPEND util_runtime_sources usrp_e3x0_network_mode.cpp) -    endif(UDEV_FOUND) -endif(ENABLE_E300 AND NOT E300_FORCE_NETWORK) -  #for each source: build an executable and install  foreach(util_source ${util_runtime_sources})      get_filename_component(util_name ${util_source} NAME_WE)  | 
