diff options
Diffstat (limited to 'host/lib/usrp/x400')
-rw-r--r-- | host/lib/usrp/x400/x400_gpio_control.cpp | 37 | ||||
-rw-r--r-- | host/lib/usrp/x400/x400_gpio_control.hpp | 17 | ||||
-rw-r--r-- | host/lib/usrp/x400/x400_radio_control.cpp | 30 | ||||
-rw-r--r-- | host/lib/usrp/x400/x400_radio_control.hpp | 49 |
4 files changed, 118 insertions, 15 deletions
diff --git a/host/lib/usrp/x400/x400_gpio_control.cpp b/host/lib/usrp/x400/x400_gpio_control.cpp index 3213f6e64..18599eb88 100644 --- a/host/lib/usrp/x400/x400_gpio_control.cpp +++ b/host/lib/usrp/x400/x400_gpio_control.cpp @@ -6,6 +6,7 @@ #include "x400_gpio_control.hpp" + using namespace uhd::rfnoc::x400; namespace { @@ -33,6 +34,9 @@ constexpr uint32_t DIO_DIRECTION_REG = 0x4; // There are two ports, each with 12 pins constexpr size_t NUM_PINS_PER_PORT = 12; +// Start of Port B pin numbers relative to Port A: +constexpr size_t PORT_NUMBER_OFFSET = 16; + // These values should match the values in MPM's x4xx_periphs.py "DIO_PORT_MAP" constexpr uint32_t PORTA_MAPPING[12] = {1, 0, 2, 3, 5, 4, 6, 7, 9, 8, 10, 11}; constexpr uint32_t PORTB_MAPPING[12] = {10, 11, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0}; @@ -40,7 +44,8 @@ constexpr uint32_t PORTB_MAPPING[12] = {10, 11, 9, 8, 6, 7, 5, 4, 2, 3, 1, 0}; const char* uhd::rfnoc::x400::GPIO_BANK_NAME = "GPIO"; -gpio_control::gpio_control(uhd::usrp::x400_rpc_iface::sptr rpcc, uhd::wb_iface::sptr iface) +gpio_control::gpio_control( + uhd::usrp::x400_rpc_iface::sptr rpcc, uhd::wb_iface::sptr iface) : _rpcc(rpcc), _regs(iface) { _rpcc->dio_set_port_mapping("DIO"); @@ -87,8 +92,10 @@ void gpio_control::set_gpio_attr( bool gpio_control::is_atr_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr) { - return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X || attr == uhd::usrp::gpio_atr::GPIO_ATR_RX - || attr == uhd::usrp::gpio_atr::GPIO_ATR_TX || attr == uhd::usrp::gpio_atr::GPIO_ATR_XX; + return attr == uhd::usrp::gpio_atr::GPIO_ATR_0X + || attr == uhd::usrp::gpio_atr::GPIO_ATR_RX + || attr == uhd::usrp::gpio_atr::GPIO_ATR_TX + || attr == uhd::usrp::gpio_atr::GPIO_ATR_XX; } uint32_t gpio_control::internalize_value(const uint32_t value) @@ -125,3 +132,27 @@ uint32_t gpio_control::get_gpio_attr(const uhd::usrp::gpio_atr::gpio_attr_t attr return publicize_value(_gpios[0]->get_attr_reg(attr)); } + +uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::map_value(const uint32_t& value) +{ + const uint32_t bank = value >= NUM_PINS_PER_PORT ? 1 : 0; + uint32_t pin_intern = value % NUM_PINS_PER_PORT; + const uint32_t* const mapping = bank == 1 ? PORTB_MAPPING : PORTA_MAPPING; + for (size_t i = 0; i < NUM_PINS_PER_PORT; i++) { + if (mapping[i] == pin_intern) { + return i + (bank * PORT_NUMBER_OFFSET); + } + } + throw uhd::lookup_error( + "Could not find corresponding GPIO pin number for given SPI pin " + value); + return 0; +} + +uint32_t uhd::rfnoc::x400::x400_gpio_port_mapping::unmap_value(const uint32_t& value) +{ + const uint32_t bank = value >= PORT_NUMBER_OFFSET ? 1 : 0; + uint32_t pin_number = value % PORT_NUMBER_OFFSET; + const uint32_t* const mapping = bank == 1 ? PORTB_MAPPING : PORTA_MAPPING; + UHD_ASSERT_THROW(pin_number < NUM_PINS_PER_PORT); + return mapping[pin_number] + (bank * NUM_PINS_PER_PORT); +}
\ No newline at end of file diff --git a/host/lib/usrp/x400/x400_gpio_control.hpp b/host/lib/usrp/x400/x400_gpio_control.hpp index a0c0593ec..01cfc134e 100644 --- a/host/lib/usrp/x400/x400_gpio_control.hpp +++ b/host/lib/usrp/x400/x400_gpio_control.hpp @@ -6,8 +6,9 @@ #pragma once -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> #include <uhdlib/usrp/common/rpc.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> +#include <uhdlib/usrp/cores/gpio_port_mapper.hpp> #include <vector> namespace uhd { namespace rfnoc { namespace x400 { @@ -32,7 +33,8 @@ extern const char* GPIO_BANK_NAME; * internal radio control registers, as well as in MPM to configure the DIO * board. */ -class gpio_control { +class gpio_control +{ public: using sptr = std::shared_ptr<gpio_control>; @@ -79,4 +81,13 @@ private: std::vector<usrp::gpio_atr::gpio_atr_3000::sptr> _gpios; }; -}}} // namespace uhd::rfnoc::x400 +class x400_gpio_port_mapping : public uhd::mapper::gpio_port_mapper +{ +public: + x400_gpio_port_mapping(){}; + + uint32_t map_value(const uint32_t& value) override; + + uint32_t unmap_value(const uint32_t& value) override; +}; +}}} // namespace uhd::rfnoc::x400
\ No newline at end of file diff --git a/host/lib/usrp/x400/x400_radio_control.cpp b/host/lib/usrp/x400/x400_radio_control.cpp index a58f522bf..75719f6a2 100644 --- a/host/lib/usrp/x400/x400_radio_control.cpp +++ b/host/lib/usrp/x400/x400_radio_control.cpp @@ -5,14 +5,17 @@ // #include "x400_radio_control.hpp" +#include "x400_gpio_control.hpp" #include <uhd/rfnoc/registry.hpp> +#include <uhd/types/serial.hpp> #include <uhd/utils/log.hpp> #include <uhd/utils/math.hpp> +#include <uhdlib/rfnoc/reg_iface_adapter.hpp> #include <uhdlib/usrp/common/x400_rfdc_control.hpp> +#include <uhdlib/usrp/cores/spi_core_4000.hpp> #include <uhdlib/usrp/dboard/debug_dboard.hpp> #include <uhdlib/usrp/dboard/null_dboard.hpp> #include <uhdlib/usrp/dboard/zbx/zbx_dboard.hpp> -#include <uhdlib/rfnoc/reg_iface_adapter.hpp> namespace uhd { namespace rfnoc { @@ -182,8 +185,25 @@ x400_radio_control_impl::x400_radio_control_impl(make_args_ptr make_args) auto mpm_rpc = _mb_control->dynamic_cast_rpc_as<uhd::usrp::mpmd_rpc_iface>(); if (mpm_rpc->get_gpio_banks().size() > 0) { - _gpios = std::make_shared<x400::gpio_control>(_rpcc, - RFNOC_MAKE_WB_IFACE(regmap::PERIPH_BASE + 0xC000, 0)); + _gpios = std::make_shared<x400::gpio_control>( + _rpcc, RFNOC_MAKE_WB_IFACE(regmap::PERIPH_BASE + 0xC000, 0)); + + auto gpio_port_mapper = std::shared_ptr<uhd::mapper::gpio_port_mapper>( + new uhd::rfnoc::x400::x400_gpio_port_mapping); + auto spicore = uhd::cores::spi_core_4000::make( + [this](const uint32_t addr, const uint32_t data) { + regs().poke32(addr, data, get_command_time(0)); + }, + [this]( + const uint32_t addr) { return regs().peek32(addr, get_command_time(0)); }, + x400_regs::SPI_SLAVE_CFG, + x400_regs::SPI_TRANSACTION_CFG_REG, + x400_regs::SPI_TRANSACTION_GO_REG, + x400_regs::SPI_STATUS_REG, + gpio_port_mapper); + + _spi_getter_iface = std::make_shared<x400_spi_getter>(spicore); + register_feature(_spi_getter_iface); } } @@ -328,8 +348,8 @@ double x400_radio_control_impl::set_rate(const double rate) // X400 does not support runtime rate changes if (!uhd::math::frequencies_are_equal(rate, get_rate())) { RFNOC_LOG_WARNING("Requesting invalid sampling rate from device: " - << (rate / 1e6) << " MHz. Actual rate is: " - << (get_rate() / 1e6) << " MHz."); + << (rate / 1e6) + << " MHz. Actual rate is: " << (get_rate() / 1e6) << " MHz."); } return get_rate(); } diff --git a/host/lib/usrp/x400/x400_radio_control.hpp b/host/lib/usrp/x400/x400_radio_control.hpp index 8848926c7..cd45291bc 100644 --- a/host/lib/usrp/x400/x400_radio_control.hpp +++ b/host/lib/usrp/x400/x400_radio_control.hpp @@ -7,24 +7,28 @@ #pragma once #include "adc_self_calibration.hpp" +#include "x400_gpio_control.hpp" +#include <uhd/features/spi_getter_iface.hpp> #include <uhd/rfnoc/noc_block_base.hpp> #include <uhd/types/device_addr.hpp> #include <uhd/types/direction.hpp> #include <uhd/types/ranges.hpp> #include <uhdlib/features/fpga_load_notification_iface.hpp> #include <uhdlib/rfnoc/radio_control_impl.hpp> +#include <uhdlib/rfnoc/reg_iface_adapter.hpp> #include <uhdlib/rfnoc/rf_control/dboard_iface.hpp> #include <uhdlib/usrp/common/mpmd_mb_controller.hpp> #include <uhdlib/usrp/common/rpc.hpp> #include <uhdlib/usrp/common/x400_rfdc_control.hpp> +#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> +#include <uhdlib/usrp/cores/spi_core_4000.hpp> #include <uhdlib/utils/rpc.hpp> #include <stddef.h> #include <memory> #include <mutex> #include <string> #include <vector> -#include <uhdlib/usrp/cores/gpio_atr_3000.hpp> -#include "x400_gpio_control.hpp" + namespace uhd { namespace rfnoc { @@ -34,6 +38,22 @@ namespace x400_regs { // other things in the RFDC. constexpr uint32_t RFDC_CTRL_BASE = radio_control_impl::regmap::PERIPH_BASE + 0x8000; +constexpr uint32_t DIO_REGMAP_OFFSET = 0x2000; +constexpr uint32_t DIO_WINDOW_OFFSET = 0xC000; + +// SPI control registers +constexpr uint32_t SPI_SLAVE_CFG = + DIO_REGMAP_OFFSET + DIO_WINDOW_OFFSET + radio_control_impl::regmap::PERIPH_BASE; + +//! Base address for SPI_TRANSACTION_CONFIG Register +constexpr uint32_t SPI_TRANSACTION_CFG_REG = SPI_SLAVE_CFG + 0x0010; + +//! Base address for SPI_TRANSACTION_GO Register +constexpr uint32_t SPI_TRANSACTION_GO_REG = SPI_SLAVE_CFG + 0x0014; + +//! Base address for SPI_STATUS Register +constexpr uint32_t SPI_STATUS_REG = SPI_SLAVE_CFG + 0x0018; + } // namespace x400_regs class x400_radio_control_impl : public radio_control_impl @@ -116,8 +136,7 @@ public: const std::string& name, const size_t chan) override; void set_rx_lo_export_enabled( bool enabled, const std::string& name, const size_t chan) override; - bool get_rx_lo_export_enabled( - const std::string& name, const size_t chan) override; + bool get_rx_lo_export_enabled(const std::string& name, const size_t chan) override; double set_rx_lo_freq( double freq, const std::string& name, const size_t chan) override; double get_rx_lo_freq(const std::string& name, const size_t chan) override; @@ -179,6 +198,8 @@ private: uhd::features::adc_self_calibration_iface::sptr _adc_self_calibration; + uhd::features::spi_getter_iface::sptr _spi_getter_iface; + x400::gpio_control::sptr _gpios; class fpga_onload : public uhd::features::fpga_load_notification_iface @@ -203,6 +224,26 @@ private: }; fpga_onload::sptr _fpga_onload; + + class x400_spi_getter : public uhd::features::spi_getter_iface + { + public: + using sptr = std::shared_ptr<spi_getter_iface>; + + x400_spi_getter(uhd::cores::spi_core_4000::sptr _spi) : _spicore(_spi) {} + + uhd::spi_iface::sptr get_spi_ref( + const std::vector<uhd::features::spi_slave_config_t>& spi_slave_config) + const override + { + _spicore->set_spi_slave_config(spi_slave_config); + return _spicore; + } + + private: + uhd::cores::spi_core_4000::sptr _spicore; + }; }; + }} // namespace uhd::rfnoc |