diff options
-rw-r--r-- | fpga/usrp3/top/x300/bus_int.v | 13 | ||||
-rw-r--r-- | fpga/usrp3/top/x300/x300_core.v | 39 | ||||
-rw-r--r-- | host/examples/gpio.cpp | 48 | ||||
-rw-r--r-- | host/lib/usrp/multi_usrp_python.hpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_mb_controller.cpp | 105 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_mb_controller.hpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_radio_control.cpp | 47 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_regs.hpp | 4 |
8 files changed, 209 insertions, 54 deletions
diff --git a/fpga/usrp3/top/x300/bus_int.v b/fpga/usrp3/top/x300/bus_int.v index faf4f8d82..92bea5d84 100644 --- a/fpga/usrp3/top/x300/bus_int.v +++ b/fpga/usrp3/top/x300/bus_int.v @@ -45,6 +45,8 @@ module bus_int #( input SFPP0_ModAbs, input SFPP0_TxFault, input SFPP0_RxLOS, inout SFPP0_RS0, inout SFPP0_RS1, // SFP+ 1 input SFPP1_ModAbs, input SFPP1_TxFault, input SFPP1_RxLOS, inout SFPP1_RS0, inout SFPP1_RS1, + // Front-panel GPIO source + output [23:0] fp_gpio_src, // Clock control and status input [7:0] clock_status, output [7:0] clock_control, output [31:0] ref_freq, output ref_freq_changed, // SFP+ 0 data stream @@ -153,7 +155,7 @@ module bus_int #( localparam SR_SPI = 8'd32; localparam SR_ETHINT0 = 8'd40; localparam SR_ETHINT1 = 8'd56; - //localparam SR_NEXT_ADDR = 8'd72; + localparam SR_FP_GPIO_SRC = 8'd72; localparam SR_BASE_TIME = 8'd100; localparam RB_COUNTER = 8'd00; @@ -169,6 +171,7 @@ module bus_int #( localparam RB_GIT_HASH = 8'd10; localparam RB_XADC_VALS = 8'd11; localparam RB_NUM_TIMEKEEPERS = 8'd12; + localparam RB_FP_GPIO_SRC = 8'd13; localparam COMPAT_MAJOR = 16'h0026; localparam COMPAT_MINOR = 16'h0000; @@ -433,6 +436,7 @@ module bus_int #( `endif RB_GIT_HASH: rb_data = `GIT_HASH; RB_XADC_VALS: rb_data = xadc_readback; + RB_FP_GPIO_SRC: rb_data = fp_gpio_src; SR_BASE_TIME: begin rb_data = radio_time[31:0]; radio_time_hi_ld = 1'b1; @@ -604,6 +608,13 @@ module bus_int #( assign SFPP1_RS0 = sfpp1_ctrl[0] ? 1'b0 : 1'bz; assign SFPP1_RS1 = sfpp1_ctrl[1] ? 1'b0 : 1'bz; + + // Front-panel GPIO source - Each pin is allocated 2 bits + setting_reg #(.my_addr(SR_FP_GPIO_SRC), .awidth(SR_AWIDTH), .width(24)) set_fp_gpio_src + (.clk(clk), .rst(reset), + .strobe(set_stb), .addr(set_addr), .in(set_data), + .out(fp_gpio_src)); + // //////////////////////////////////////////////////////////////// // ETH interfaces diff --git a/fpga/usrp3/top/x300/x300_core.v b/fpga/usrp3/top/x300/x300_core.v index 0a721e06b..5665c397f 100644 --- a/fpga/usrp3/top/x300/x300_core.v +++ b/fpga/usrp3/top/x300/x300_core.v @@ -1,6 +1,7 @@ // // Copyright 2014 Ettus Research LLC // Copyright 2017 Ettus Research, a National Instruments Company +// Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // @@ -21,7 +22,7 @@ module x300_core #( // Radio 0 input [31:0] rx0, output [31:0] tx0, input [31:0] db0_gpio_in, output [31:0] db0_gpio_out, output [31:0] db0_gpio_ddr, - input [31:0] fp_gpio_in, output [31:0] fp_gpio_out, output [31:0] fp_gpio_ddr, + input [31:0] fp_gpio_in, output reg [31:0] fp_gpio_out, output reg [31:0] fp_gpio_ddr, output [7:0] sen0, output sclk0, output mosi0, input miso0, output [2:0] radio_led0, output reg [31:0] radio0_misc_out, input [31:0] radio0_misc_in, @@ -311,6 +312,8 @@ module x300_core #( // SFP 1 .SFPP1_ModAbs(SFPP1_ModAbs),.SFPP1_TxFault(SFPP1_TxFault),.SFPP1_RxLOS(SFPP1_RxLOS), .SFPP1_RS0(SFPP1_RS0), .SFPP1_RS1(SFPP1_RS1), + // Front-panel GPIO source + .fp_gpio_src(sr_fp_gpio_src), //clocky locky misc .clock_status({misc_clock_status, pps_detect, LMK_Holdover, LMK_Lock, LMK_Status}), .clock_control({1'b0, clock_misc_opt[1:0], pps_out_enb, pps_select[1:0], clock_ref_sel[1:0]}), @@ -528,6 +531,7 @@ module x300_core #( wire [31:0] db_gpio_in[0:NUM_DBOARDS-1], db_gpio_out[0:NUM_DBOARDS-1], db_gpio_ddr[0:NUM_DBOARDS-1]; wire [31:0] misc_outs[0:NUM_DBOARDS-1]; reg [31:0] misc_ins[0:NUM_DBOARDS-1]; + wire [24:0] sr_fp_gpio_src, fp_gpio_src; wire [7:0] sen[0:NUM_DBOARDS-1]; wire sclk[0:NUM_DBOARDS-1], mosi[0:NUM_DBOARDS-1], miso[0:NUM_DBOARDS-1]; wire rx_running[0:NUM_CHANNELS-1], tx_running[0:NUM_CHANNELS-1]; @@ -602,6 +606,34 @@ module x300_core #( endgenerate //------------------------------------ + // Front-Panel GPIO Source Mux + //------------------------------------ + // Number of FP GPIO Pins + localparam FP_GPIO_WIDTH = 12; + + // Bring FP GPIO controls into radio clk domain + synchronizer #(.WIDTH(24)) fp_gpio_sync ( + .clk(radio_clk), .rst(radio_rst), .in(sr_fp_gpio_src), .out(fp_gpio_src) + ); + + // For each bit in the front-panel GPIO, mux the output and the direction + // control bit based on the fp_gpio_src register. The fp_gpio_src register + // holds 2 bits per GPIO pin, which selects which source to use for GPIO + // control. Currently, only daughter board 0 and daughter board 1 are + // supported. + for (i=0; i<FP_GPIO_WIDTH; i=i+1) begin : gen_fp_gpio_mux + always @(posedge radio_clk) begin + fp_gpio_out[i] <= fp_gpio_r_out[fp_gpio_src[2*i +: 2] == 0 ? 0 : 1][i]; + fp_gpio_ddr[i] <= fp_gpio_r_ddr[fp_gpio_src[2*i +: 2] == 0 ? 0 : 1][i]; + end + end + + // Front-panel GPIO inputs are routed to all daughter boards + for (i=0; i<NUM_DBOARDS; i=i+1) begin : gen_fp_gpio_inputs + assign fp_gpio_r_in[i] = fp_gpio_in; + end + + //------------------------------------ // Radio to ADC,DAC and IO Mapping //------------------------------------ @@ -653,11 +685,6 @@ module x300_core #( assign db0_gpio_ddr = db_gpio_ddr[0]; assign db1_gpio_ddr = db_gpio_ddr[1]; - //Front-panel board GPIO - assign {fp_gpio_r_in[1], fp_gpio_r_in[0]} = {32'b0, fp_gpio_in}; - assign fp_gpio_out = fp_gpio_r_out[0]; //fp_gpio_r_out[1] unused - assign fp_gpio_ddr = fp_gpio_r_ddr[0]; //fp_gpio_ddr[1] unused - //SPI assign {sen0, sclk0, mosi0} = {sen[0], sclk[0], mosi[0]}; assign miso[0] = miso0; diff --git a/host/examples/gpio.cpp b/host/examples/gpio.cpp index fdd65349e..779fc1fa0 100644 --- a/host/examples/gpio.cpp +++ b/host/examples/gpio.cpp @@ -1,6 +1,7 @@ // // Copyright 2014-15 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company +// Copyright 2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // @@ -48,8 +49,11 @@ // ATR_TX - Output values to be set when transmitting // ATR_XX - Output values to be set when operating in full duplex // This code below contains examples of setting all these registers. On -// devices with multiple radios, the ATR for the front panel GPIO is driven -// by the state of the first radio (0 or A). +// devices with multiple radios, the ATR driver for the front panel GPIO +// defaults to the state of the first radio (0 or A). This can be changed +// on a bit-by-bit basis by writing to the register: +// The ATR source can also be controlled, ie. drive from Radio0 or Radio1. +// SRC - Source (RFA=Radio0, RFB=Radio1, etc.) // // The UHD API // The multi_usrp::set_gpio_attr() method is the UHD API for configuring and @@ -57,8 +61,9 @@ // bank - the name of the GPIO bank (typically "FP0" for front panel GPIO, // "TX<n>" for TX daughter card GPIO, or // "RX<n>" for RX daughter card GPIO) -// attr - attribute (register) to change ("DDR", "OUT", "CTRL", "ATR_0X", -// "ATR_RX", "ATR_TX", "ATR_XX") +// attr - attribute (register) to change ("SRC", "DDR", "OUT", "CTRL", +// "ATR_0X", "ATR_RX", "ATR_TX", +// "ATR_XX") // value - the value to be set // mask - a mask indicating which bits in the specified attribute register are // to be changed (default is all bits). @@ -71,6 +76,7 @@ #include <stdlib.h> #include <boost/format.hpp> #include <boost/program_options.hpp> +#include <boost/tokenizer.hpp> #include <chrono> #include <csignal> #include <iostream> @@ -127,6 +133,13 @@ void output_reg_values(const std::string bank, % to_bit_string(gpio_bits, num_bits)) << std::endl; } + // GPIO Src + const auto gpio_src = usrp->get_gpio_src(bank); + std::cout << boost::format("%10s:") % "SRC: "; + for (auto src : gpio_src) { + std::cout << " " << src; + } + std::cout << std::endl; } int UHD_SAFE_MAIN(int argc, char* argv[]) @@ -137,9 +150,12 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) double rx_rate, tx_rate, dwell; std::string gpio; size_t num_bits; + std::string src_str; std::string ctrl_str; std::string ddr_str; std::string out_str; + std::string tx_subdev_spec; + std::string rx_subdev_spec; // setup the program options po::options_description desc("Allowed options"); @@ -147,6 +163,8 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) desc.add_options() ("help", "help message") ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args") + ("tx_subdev_spec", po::value<std::string>(&tx_subdev_spec)->default_value(""), "A:0, B:0, or A:0 B:0") + ("rx_subdev_spec", po::value<std::string>(&rx_subdev_spec)->default_value(""), "A:0, B:0, or A:0 B:0") ("repeat", "repeat loop until Ctrl-C is pressed") ("list-banks", "print list of banks before running tests") ("cpu", po::value<std::string>(&cpu)->default_value(GPIO_DEFAULT_CPU_FORMAT), "cpu data format") @@ -157,6 +175,7 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) ("bank", po::value<std::string>(&gpio)->default_value(GPIO_DEFAULT_GPIO), "name of gpio bank") ("bits", po::value<size_t>(&num_bits)->default_value(GPIO_DEFAULT_NUM_BITS), "number of bits in gpio bank") ("bitbang", "single test case where user sets values for CTRL, DDR, and OUT registers") + ("src", po::value<std::string>(&src_str), "GPIO SRC reg value") ("ddr", po::value<std::string>(&ddr_str)->default_value(GPIO_DEFAULT_DDR), "GPIO DDR reg value") ("out", po::value<std::string>(&out_str)->default_value(GPIO_DEFAULT_OUT), "GPIO OUT reg value") ; @@ -187,6 +206,18 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) } std::cout << "Using GPIO bank: " << gpio << std::endl; + // subdev spec + if (tx_subdev_spec != "") + usrp->set_tx_subdev_spec(tx_subdev_spec); + if (rx_subdev_spec != "") + usrp->set_rx_subdev_spec(rx_subdev_spec); + std::cout << boost::format(" rx_subdev_spec: %s") + % usrp->get_rx_subdev_spec(0).to_string() + << std::endl; + std::cout << boost::format(" tx_subdev_spec: %s") + % usrp->get_tx_subdev_spec(0).to_string() + << std::endl; + // print out initial unconfigured state of FP GPIO std::cout << "Initial GPIO values:" << std::endl; output_reg_values(gpio, usrp, num_bits); @@ -227,6 +258,15 @@ int UHD_SAFE_MAIN(int argc, char* argv[]) ddr |= GPIO_BIT(4); } + // set GPIO driver source + if (vm.count("src")) { + std::vector<std::string> gpio_src; + typedef boost::char_separator<char> separator; + boost::tokenizer<separator> tokens(src_str, separator(" ")); + std::copy(tokens.begin(), tokens.end(), std::back_inserter(gpio_src)); + usrp->set_gpio_src(gpio, gpio_src); + } + // set data direction register (DDR) usrp->set_gpio_attr(gpio, "DDR", ddr, mask); diff --git a/host/lib/usrp/multi_usrp_python.hpp b/host/lib/usrp/multi_usrp_python.hpp index c9d89888b..8d25e26d4 100644 --- a/host/lib/usrp/multi_usrp_python.hpp +++ b/host/lib/usrp/multi_usrp_python.hpp @@ -24,6 +24,7 @@ void export_multi_usrp(py::module& m) // Factory .def(py::init(&multi_usrp::make)) + // clang-format off // General USRP methods .def("get_rx_freq" , &multi_usrp::get_rx_freq, py::arg("chan") = 0) .def("get_rx_num_channels" , &multi_usrp::get_rx_num_channels) @@ -170,6 +171,7 @@ void export_multi_usrp(py::module& m) .def("get_gpio_srcs" , &multi_usrp::get_gpio_srcs, py::arg("bank"), py::arg("mboard") = 0) .def("get_gpio_src" , &multi_usrp::get_gpio_src, py::arg("bank"), py::arg("mboard") = 0) .def("set_gpio_src" , &multi_usrp::set_gpio_src, py::arg("bank"), py::arg("src"), py::arg("mboard") = 0) + .def("get_gpio_src_banks" , &multi_usrp::get_gpio_src_banks, py::arg("mboard") = 0) // Filter API methods .def("get_rx_filter_names" , &multi_usrp::get_rx_filter_names) @@ -178,6 +180,7 @@ void export_multi_usrp(py::module& m) .def("get_tx_filter_names" , &multi_usrp::get_tx_filter_names) .def("get_tx_filter" , &multi_usrp::get_tx_filter) .def("set_tx_filter" , &multi_usrp::set_tx_filter) + // clang-format off ; } diff --git a/host/lib/usrp/x300/x300_mb_controller.cpp b/host/lib/usrp/x300/x300_mb_controller.cpp index fd70526ab..28567e62e 100644 --- a/host/lib/usrp/x300/x300_mb_controller.cpp +++ b/host/lib/usrp/x300/x300_mb_controller.cpp @@ -1,5 +1,5 @@ // -// Copyright 2019 Ettus Research, a National Instruments Brand +// Copyright 2019-2020 Ettus Research, a National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // @@ -26,7 +26,7 @@ constexpr uint32_t ADC_SELF_TEST_DURATION = 100; // ms // When these regs are fixed, there is another fixme below to actually init the // timekeepers -constexpr uint32_t TK_NUM_TIMEKEEPERS = 12; //Read-only +constexpr uint32_t TK_NUM_TIMEKEEPERS = 12; // Read-only constexpr uint32_t TK_REG_BASE = 100; constexpr uint32_t TK_REG_OFFSET = 48; constexpr uint32_t TK_REG_TICKS_NOW_LO = 0x00; // Read-only @@ -41,6 +41,11 @@ constexpr uint32_t TK_REG_TICKS_PERIOD_HI = 0x20; // Read-Write constexpr char LOG_ID[] = "X300::MB_CTRL"; +constexpr char GPIO_SRC_BANK[] = "FP0"; +constexpr char GPIO_SRC_RFA[] = "RFA"; +constexpr char GPIO_SRC_RFB[] = "RFB"; +constexpr size_t GPIO_SRC_NUM_PINS = 12; + } // namespace @@ -75,7 +80,9 @@ x300_mb_controller::x300_mb_controller(const size_t hw_rev, const size_t num_tks = _zpu_ctrl->peek32(SR_ADDR(SET0_BASE, TK_NUM_TIMEKEEPERS)); for (size_t i = 0; i < num_tks; i++) { - register_timekeeper(i, std::make_shared<x300_timekeeper>(i, _zpu_ctrl, clock_ctrl->get_master_clock_rate())); + register_timekeeper(i, + std::make_shared<x300_timekeeper>( + i, _zpu_ctrl, clock_ctrl->get_master_clock_rate())); } init_gps(); @@ -107,8 +114,7 @@ void x300_mb_controller::x300_timekeeper::set_ticks_now(const uint64_t ticks) get_tk_addr(TK_REG_TICKS_EVENT_LO), narrow_cast<uint32_t>(ticks & 0xFFFFFFFF)); _zpu_ctrl->poke32( get_tk_addr(TK_REG_TICKS_EVENT_HI), narrow_cast<uint32_t>(ticks >> 32)); - _zpu_ctrl->poke32( - get_tk_addr(TK_REG_TICKS_CTRL), narrow_cast<uint32_t>(0x1)); + _zpu_ctrl->poke32(get_tk_addr(TK_REG_TICKS_CTRL), narrow_cast<uint32_t>(0x1)); } void x300_mb_controller::x300_timekeeper::set_ticks_next_pps(const uint64_t ticks) @@ -117,16 +123,15 @@ void x300_mb_controller::x300_timekeeper::set_ticks_next_pps(const uint64_t tick get_tk_addr(TK_REG_TICKS_EVENT_LO), narrow_cast<uint32_t>(ticks & 0xFFFFFFFF)); _zpu_ctrl->poke32( get_tk_addr(TK_REG_TICKS_EVENT_HI), narrow_cast<uint32_t>(ticks >> 32)); - _zpu_ctrl->poke32( - get_tk_addr(TK_REG_TICKS_CTRL), narrow_cast<uint32_t>(0x2)); + _zpu_ctrl->poke32(get_tk_addr(TK_REG_TICKS_CTRL), narrow_cast<uint32_t>(0x2)); } void x300_mb_controller::x300_timekeeper::set_period(const uint64_t period_ns) { _zpu_ctrl->poke32(get_tk_addr(TK_REG_TICKS_PERIOD_LO), narrow_cast<uint32_t>(period_ns & 0xFFFFFFFF)); - _zpu_ctrl->poke32(get_tk_addr(TK_REG_TICKS_PERIOD_HI), - narrow_cast<uint32_t>(period_ns >> 32)); + _zpu_ctrl->poke32( + get_tk_addr(TK_REG_TICKS_PERIOD_HI), narrow_cast<uint32_t>(period_ns >> 32)); } uint32_t x300_mb_controller::x300_timekeeper::get_tk_addr(const uint32_t tk_addr) @@ -247,8 +252,8 @@ void x300_mb_controller::set_clock_source(const std::string& source) .str()); } else { // TODO: Re-enable this warning when we figure out a reliable lock time - // UHD_LOGGER_WARNING("X300::MB_CTRL") << "Reference clock failed to lock to " + - // source + " during device initialization. " << + // UHD_LOGGER_WARNING("X300::MB_CTRL") << "Reference clock failed to lock + // to " + source + " during device initialization. " << // "Check for the lock before operation or ignore this warning if using // another clock source." ; } @@ -311,7 +316,8 @@ void x300_mb_controller::set_sync_source( set_sync_source(sync_args); } -void x300_mb_controller::set_sync_source(const device_addr_t& sync_source) { +void x300_mb_controller::set_sync_source(const device_addr_t& sync_source) +{ if (sync_source.has_key("clock_source")) { set_clock_source(sync_source["clock_source"]); } @@ -338,8 +344,7 @@ std::vector<device_addr_t> x300_mb_controller::get_sync_sources() {"external", "internal"}, {"external", "external"}, {"gpsdo", "gpsdo"}, - {"gpsdo", "internal"} - }; + {"gpsdo", "internal"}}; // Now convert to vector of device_addr_t std::vector<device_addr_t> sync_sources; @@ -484,6 +489,78 @@ bool x300_mb_controller::synchronize(std::vector<mb_controller::sptr>& mb_contro throw uhd::runtime_error(err_str); } +std::vector<std::string> x300_mb_controller::get_gpio_banks() const +{ + return {GPIO_SRC_BANK}; +} + +std::vector<std::string> x300_mb_controller::get_gpio_srcs(const std::string& bank) const +{ + if (bank != GPIO_SRC_BANK) { + UHD_LOG_ERROR(LOG_ID, + "Invalid GPIO source bank: " << bank << ". Only supported bank is " + << GPIO_SRC_BANK); + throw uhd::runtime_error( + std::string("Invalid GPIO source bank: ") + GPIO_SRC_BANK); + } + return {GPIO_SRC_RFA, GPIO_SRC_RFB}; +} + +std::vector<std::string> x300_mb_controller::get_gpio_src(const std::string& bank) +{ + if (bank != GPIO_SRC_BANK) { + UHD_LOG_ERROR(LOG_ID, + "Invalid GPIO source bank: " << bank << ". Only supported bank is " + << GPIO_SRC_BANK); + throw uhd::runtime_error( + std::string("Invalid GPIO source bank: ") + GPIO_SRC_BANK); + } + uint32_t fp_gpio_src = _zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_FP_GPIO_SRC)); + const auto gpio_srcs = get_gpio_srcs(bank); + std::vector<std::string> gpio_src; + for (size_t ii = 0; ii < GPIO_SRC_NUM_PINS; ++ii) { + const uint32_t this_src = (fp_gpio_src >> (2 * ii)) & 0x3; + if (this_src > 1) { + UHD_LOG_WARNING(LOG_ID, + "get_gpio_src() read back invalid GPIO source index: " + << this_src << ". Falling back to " << (this_src & 0x1)); + } + gpio_src.push_back(gpio_srcs[this_src & 0x1]); + } + return gpio_src; +} + +void x300_mb_controller::set_gpio_src( + const std::string& bank, const std::vector<std::string>& srcs) +{ + if (srcs.size() > GPIO_SRC_NUM_PINS) { + UHD_LOG_WARNING(LOG_ID, "set_gpio_src(): Provided more sources than pins!"); + } + uint32_t fp_gpio_src = _zpu_ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_FP_GPIO_SRC)); + size_t pins_configured = 0; + + const auto gpio_srcs = get_gpio_srcs(bank); + for (auto src : srcs) { + const uint32_t pins = [src]() { + if (src == GPIO_SRC_RFA) { + return 0; + } + if (src == GPIO_SRC_RFB) { + return 1; + } + UHD_LOG_ERROR(LOG_ID, "Invalid GPIO source provided: " << src); + throw uhd::runtime_error("Invalid GPIO source provided!"); + }(); + uint32_t pin_mask = ~(uint32_t(0x3) << (2 * pins_configured)); + fp_gpio_src = (fp_gpio_src & pin_mask) | (pins << 2 * pins_configured); + pins_configured++; + if (pins_configured > GPIO_SRC_NUM_PINS) { + break; + } + } + _zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_FP_GPIO_SRC), fp_gpio_src); +} + /****************************************************************************** * Private Methods *****************************************************************************/ diff --git a/host/lib/usrp/x300/x300_mb_controller.hpp b/host/lib/usrp/x300/x300_mb_controller.hpp index 53f166a0e..92844f1b9 100644 --- a/host/lib/usrp/x300/x300_mb_controller.hpp +++ b/host/lib/usrp/x300/x300_mb_controller.hpp @@ -120,6 +120,10 @@ public: bool synchronize(std::vector<mb_controller::sptr>& mb_controllers, const uhd::time_spec_t& time_spec = uhd::time_spec_t(0.0), const bool quiet = false); + std::vector<std::string> get_gpio_banks() const; + std::vector<std::string> get_gpio_srcs(const std::string&) const; + std::vector<std::string> get_gpio_src(const std::string&); + void set_gpio_src(const std::string&, const std::vector<std::string>&); private: //! Return a string X300::MB_CTRL#N diff --git a/host/lib/usrp/x300/x300_radio_control.cpp b/host/lib/usrp/x300/x300_radio_control.cpp index c41a19401..48b484467 100644 --- a/host/lib/usrp/x300/x300_radio_control.cpp +++ b/host/lib/usrp/x300/x300_radio_control.cpp @@ -147,27 +147,24 @@ public: _init_codecs(); _x300_mb_control->register_reset_codec_cb([this]() { this->reset_codec(); }); // FP-GPIO - if (_radio_type == PRIMARY) { - RFNOC_LOG_TRACE("Creating FP-GPIO interface..."); - _fp_gpio = gpio_atr::gpio_atr_3000::make(_wb_iface, - x300_regs::SR_FP_GPIO, - x300_regs::RB_FP_GPIO, - x300_regs::PERIPH_REG_OFFSET); - // Create the GPIO banks and attributes, and populate them with some default - // values - // TODO: Do we need this section? Since the _fp_gpio handles state now, we - // don't need to stash values here. We only need this if we want to set - // anything to a default value. - for (const gpio_atr::gpio_attr_map_t::value_type attr : - gpio_atr::gpio_attr_map) { - // TODO: Default values? - if (attr.first == usrp::gpio_atr::GPIO_SRC) { - // Don't set the SRC - // TODO: Remove from the map?? - continue; - } - set_gpio_attr("FP0", usrp::gpio_atr::gpio_attr_map.at(attr.first), 0); + RFNOC_LOG_TRACE("Creating FP-GPIO interface..."); + _fp_gpio = gpio_atr::gpio_atr_3000::make(_wb_iface, + x300_regs::SR_FP_GPIO, + x300_regs::RB_FP_GPIO, + x300_regs::PERIPH_REG_OFFSET); + // Create the GPIO banks and attributes, and populate them with some default + // values + // TODO: Do we need this section? Since the _fp_gpio handles state now, we + // don't need to stash values here. We only need this if we want to set + // anything to a default value. + for (const gpio_atr::gpio_attr_map_t::value_type attr : gpio_atr::gpio_attr_map) { + // TODO: Default values? + if (attr.first == usrp::gpio_atr::GPIO_SRC) { + // Don't set the SRC + // TODO: Remove from the map?? + continue; } + set_gpio_attr("FP0", usrp::gpio_atr::gpio_attr_map.at(attr.first), 0); } // DB Initialization _init_db(); // This does not init the dboards themselves! @@ -855,17 +852,13 @@ public: /*** GPIO API ************************************************************/ std::vector<std::string> get_gpio_banks() const { - std::vector<std::string> banks{"RX", "TX"}; - if (_fp_gpio) { - banks.push_back("FP0"); - } - return banks; + return {"RX", "TX", "FP0"}; } void set_gpio_attr( const std::string& bank, const std::string& attr, const uint32_t value) { - if (bank == "FP0" and _fp_gpio) { + if (bank == "FP0") { _fp_gpio->set_gpio_attr(usrp::gpio_atr::gpio_attr_rev_map.at(attr), value); return; } @@ -909,7 +902,7 @@ public: uint32_t get_gpio_attr(const std::string& bank, const std::string& attr) { - if (bank == "FP0" and _fp_gpio) { + if (bank == "FP0") { return _fp_gpio->get_attr_reg(usrp::gpio_atr::gpio_attr_rev_map.at(attr)); } if (bank.size() >= 2 and bank[1] == 'X') { diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 64ff63d77..86ffd46c4 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -35,8 +35,7 @@ static const int ZPU_SR_REF_FREQ = 04; static const int ZPU_SR_SPI = 32; static const int ZPU_SR_ETHINT0 = 40; static const int ZPU_SR_ETHINT1 = 56; -static const int ZPU_SR_DRAM_FIFO0 = 72; -static const int ZPU_SR_DRAM_FIFO1 = 80; +static const int ZPU_SR_FP_GPIO_SRC = 72; // reset bits #define ZPU_SR_SW_RST_ETH_PHY (1 << 0) @@ -51,6 +50,7 @@ static const int ZPU_RB_NUM_CE = 7; static const int ZPU_RB_GIT_HASH = 10; static const int ZPU_RB_SFP0_TYPE = 4; static const int ZPU_RB_SFP1_TYPE = 5; +static const int ZPU_RB_FP_GPIO_SRC = 13; static const uint32_t RB_SFP_1G_ETH = 0; static const uint32_t RB_SFP_10G_ETH = 1; |