aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorIan Buckley <github@ionconcepts.com>2015-03-09 11:20:56 -0700
committerAshish Chaudhari <ashish@ettus.com>2015-03-09 11:20:56 -0700
commitd9241b78d32402093c37ab7ce2f4336699219ed4 (patch)
tree4ca5dcae3226099d4d2770bee397969006dbae9c /host
parent33edac343488fdd87337e308b277adca69f16819 (diff)
downloaduhd-d9241b78d32402093c37ab7ce2f4336699219ed4.tar.gz
uhd-d9241b78d32402093c37ab7ce2f4336699219ed4.tar.bz2
uhd-d9241b78d32402093c37ab7ce2f4336699219ed4.zip
B200: UHD support for FPGPIO connector on REV6+ boards.
- GPIO on UART connector all board Revs - Consolidated fpgpio_bitbang into fpgpio example and renamed it gpio - Changed FP_GPIO readback address to match X300
Diffstat (limited to 'host')
-rw-r--r--host/examples/CMakeLists.txt2
-rw-r--r--host/examples/fpgpio.cpp418
-rw-r--r--host/examples/gpio.cpp462
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp35
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp7
-rw-r--r--host/lib/usrp/b200/b200_regs.hpp2
-rw-r--r--host/lib/usrp/cores/gpio_core_200.hpp9
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp34
-rw-r--r--host/lib/usrp/e300/e300_impl.hpp6
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp35
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp6
11 files changed, 555 insertions, 461 deletions
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index 598e42302..92947d86c 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -35,7 +35,7 @@ SET(example_sources
tx_waveforms.cpp
txrx_loopback_to_file.cpp
latency_test.cpp
- fpgpio.cpp
+ gpio.cpp
)
IF(ENABLE_OCTOCLOCK)
diff --git a/host/examples/fpgpio.cpp b/host/examples/fpgpio.cpp
deleted file mode 100644
index c57893669..000000000
--- a/host/examples/fpgpio.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-//
-// Copyright 2014 Ettus Research LLC
-//
-// 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/>.
-//
-
-// Example for front panel GPIO.
-// Bits are set as follows:
-// FPGPIO[0] = ATR output 1 at idle
-// FPGPIO[1] = ATR output 1 during RX
-// FPGPIO[2] = ATR output 1 during TX
-// FPGPIO[3] = ATR output 1 during full duplex
-// FPGPIO[4] = output
-// FPGPIO[5] = input
-// FPGPIO[6] = input (X series only)
-// FPGPIO[7] = input (X series only)
-// FPGPIO[8] = input (X series only)
-// FPGPIO[9] = input (X series only)
-// FPGPIO[10] = input (X series only)
-// The example cycles through idle, TX, RX, and full duplex, spending 2 seconds for each.
-// Outputs can be physically looped back to inputs for verification testing.
-
-#include <uhd/utils/thread_priority.hpp>
-#include <uhd/utils/safe_main.hpp>
-#include <uhd/usrp/multi_usrp.hpp>
-#include <uhd/convert.hpp>
-#include <boost/program_options.hpp>
-#include <boost/format.hpp>
-#include <boost/cstdint.hpp>
-#include <boost/thread.hpp>
-#include <csignal>
-#include <iostream>
-
-static const std::string FPGPIO_DEFAULT_CPU_FORMAT = "fc32";
-static const std::string FPGPIO_DEFAULT_OTW_FORMAT = "sc16";
-static const double FPGPIO_DEFAULT_RX_RATE = 500e3;
-static const double FPGPIO_DEFAULT_TX_RATE = 500e3;
-static const double FPGPIO_DEFAULT_DWELL_TIME = 2.0;
-static const std::string FPGPIO_DEFAULT_GPIO = "FP0";
-static const size_t FPGPIO_DEFAULT_NUM_BITS = 11;
-
-static UHD_INLINE boost::uint32_t FPGPIO_BIT(const size_t x)
-{
- return (1 << x);
-}
-
-namespace po = boost::program_options;
-
-static bool stop_signal_called = false;
-void sig_int_handler(int){stop_signal_called = true;}
-
-std::string to_bit_string(boost::uint32_t val, const size_t num_bits)
-{
- std::string out;
- for (int i = num_bits - 1; i >= 0; i--)
- {
- std::string bit = ((val >> i) & 1) ? "1" : "0";
- out += " ";
- out += bit;
- }
- return out;
-}
-
-void output_reg_values(
- const std::string bank,
- const uhd::usrp::multi_usrp::sptr &usrp,
- const size_t num_bits)
-{
- std::cout << (boost::format("Bit "));
- for (int i = num_bits - 1; i >= 0; i--)
- std::cout << (boost::format(" %s%d") % (i < 10 ? " " : "") % i);
- std::cout << std::endl;
- std::cout << "CTRL: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("CTRL"))),
- num_bits)
- << std::endl;
-
- std::cout << "DDR: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("DDR"))),
- num_bits)
- << std::endl;
-
- std::cout << "ATR_0X: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("ATR_0X"))),
- num_bits)
- << std::endl;
-
- std::cout << "ATR_RX: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("ATR_RX"))),
- num_bits)
- << std::endl;
-
- std::cout << "ATR_TX: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("ATR_TX"))),
- num_bits)
- << std::endl;
-
- std::cout << "ATR_XX: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("ATR_XX"))),
- num_bits)
- << std::endl;
-
- std::cout << "OUT: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("OUT"))),
- num_bits)
- << std::endl;
-
- std::cout << "READBACK: " << to_bit_string(
- boost::uint32_t(usrp->get_gpio_attr(bank, std::string("READBACK"))),
- num_bits)
- << std::endl;
-}
-
-int UHD_SAFE_MAIN(int argc, char *argv[])
-{
- uhd::set_thread_priority_safe();
-
- //variables to be set by po
- std::string args;
- std::string cpu, otw;
- double rx_rate, tx_rate, dwell;
- std::string fpgpio;
- size_t num_bits;
-
- //setup the program options
- po::options_description desc("Allowed options");
- desc.add_options()
- ("help", "help message")
- ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args")
- ("repeat", "repeat loop until Ctrl-C is pressed")
- ("cpu", po::value<std::string>(&cpu)->default_value(FPGPIO_DEFAULT_CPU_FORMAT), "cpu data format")
- ("otw", po::value<std::string>(&otw)->default_value(FPGPIO_DEFAULT_OTW_FORMAT), "over the wire data format")
- ("rx_rate", po::value<double>(&rx_rate)->default_value(FPGPIO_DEFAULT_RX_RATE), "rx sample rate")
- ("tx_rate", po::value<double>(&tx_rate)->default_value(FPGPIO_DEFAULT_TX_RATE), "tx sample rate")
- ("dwell", po::value<double>(&dwell)->default_value(FPGPIO_DEFAULT_DWELL_TIME), "dwell time in seconds for each test case")
- ("gpio", po::value<std::string>(&fpgpio)->default_value(FPGPIO_DEFAULT_GPIO), "name of gpio bank")
- ("bits", po::value<size_t>(&num_bits)->default_value(FPGPIO_DEFAULT_NUM_BITS), "number of bits in gpio bank")
- ;
- po::variables_map vm;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
-
- //print the help message
- if (vm.count("help")){
- std::cout << boost::format("Front Panel GPIO %s") % desc << std::endl;
- return ~0;
- }
-
- //create a usrp device
- std::cout << std::endl;
- std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
- uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
- std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
-
- //print out initial unconfigured state of FP GPIO
- std::cout << "Unconfigured GPIO values:" << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
-
- //configure GPIO registers
- boost::uint32_t ctrl = 0; // default all as manual
- boost::uint32_t ddr = 0; // default all as input
- boost::uint32_t atr_idle = 0;
- boost::uint32_t atr_rx = 0;
- boost::uint32_t atr_tx = 0;
- boost::uint32_t atr_duplex = 0;
- boost::uint32_t mask = 0x7ff;
-
- //set up FPGPIO outputs:
- //FPGPIO[0] = ATR output 1 at idle
- ctrl |= FPGPIO_BIT(0);
- atr_idle |= FPGPIO_BIT(0);
- ddr |= FPGPIO_BIT(0);
-
- //FPGPIO[1] = ATR output 1 during RX
- ctrl |= FPGPIO_BIT(1);
- ddr |= FPGPIO_BIT(1);
- atr_rx |= FPGPIO_BIT(1);
-
- //FPGPIO[2] = ATR output 1 during TX
- ctrl |= FPGPIO_BIT(2);
- ddr |= FPGPIO_BIT(2);
- atr_tx |= FPGPIO_BIT(2);
-
- //FPGPIO[3] = ATR output 1 during full duplex
- ctrl |= FPGPIO_BIT(3);
- ddr |= FPGPIO_BIT(3);
- atr_duplex |= FPGPIO_BIT(3);
-
- //FPGPIO[4] = output
- ddr |= FPGPIO_BIT(4);
-
- //set data direction register (DDR)
- usrp->set_gpio_attr(fpgpio, std::string("DDR"), ddr, mask);
-
- //set ATR registers
- usrp->set_gpio_attr(fpgpio, std::string("ATR_0X"), atr_idle, mask);
- usrp->set_gpio_attr(fpgpio, std::string("ATR_RX"), atr_rx, mask);
- usrp->set_gpio_attr(fpgpio, std::string("ATR_TX"), atr_tx, mask);
- usrp->set_gpio_attr(fpgpio, std::string("ATR_XX"), atr_duplex, mask);
-
- //set control register
- usrp->set_gpio_attr(fpgpio, std::string("CTRL"), ctrl, mask);
-
- //print out initial state of FP GPIO
- std::cout << "\nConfigured GPIO values:" << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- std::cout << std::endl;
-
- //set up streams
- uhd::stream_args_t rx_args(cpu, otw);
- uhd::stream_args_t tx_args(cpu, otw);
- uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(rx_args);
- uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(tx_args);
- uhd::stream_cmd_t rx_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
- rx_cmd.stream_now = true;
- usrp->set_rx_rate(rx_rate);
- usrp->set_tx_rate(tx_rate);
-
- //set up buffers for tx and rx
- const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
- const size_t nsamps_per_buff = max_samps_per_packet;
- std::vector<char> rx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu));
- std::vector<char> tx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu));
- std::vector<void *> rx_buffs, tx_buffs;
- for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++)
- rx_buffs.push_back(&rx_buff.front()); //same buffer for each channel
- for (size_t ch = 0; ch < tx_stream->get_num_channels(); ch++)
- tx_buffs.push_back(&tx_buff.front()); //same buffer for each channel
-
- uhd::rx_metadata_t rx_md;
- uhd::tx_metadata_t tx_md;
- tx_md.has_time_spec = false;
- tx_md.start_of_burst = true;
- uhd::time_spec_t stop_time;
- double timeout = 0.01;
- uhd::time_spec_t dwell_time(dwell);
- int loop = 0;
- boost::uint32_t rb, expected;
-
- //register singal handler
- std::signal(SIGINT, &sig_int_handler);
-
- //Test the mask - only need to test once with no dwell time
- std::cout << "\nTesting mask..." << std::flush;
- //send a value of all 1's to the DDR with a mask for only bit 10
- usrp->set_gpio_attr(fpgpio, std::string("DDR"), ~0, FPGPIO_BIT(10));
- //bit 10 should now be 1, but all the other bits should be unchanged
- rb = usrp->get_gpio_attr(fpgpio, std::string("DDR")) & mask;
- expected = ddr | FPGPIO_BIT(10);
- if (rb == expected)
- std::cout << "pass" << std::endl;
- else
- std::cout << "fail" << std::endl;
- std::cout << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- usrp->set_gpio_attr(fpgpio, std::string("DDR"), ddr, mask);
-
- while (not stop_signal_called)
- {
- int failures = 0;
-
- if (vm.count("repeat"))
- std::cout << "Press Ctrl + C to quit..." << std::endl;
-
- // test user controlled GPIO and ATR idle by setting bit 4 high for 1 second
- std::cout << "\nTesting user controlled GPIO and ATR idle output..." << std::flush;
- usrp->set_gpio_attr(fpgpio, "OUT", 1 << 4, 1 << 4);
- stop_time = usrp->get_time_now() + dwell_time;
- while (not stop_signal_called and usrp->get_time_now() < stop_time)
- {
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- }
- rb = usrp->get_gpio_attr(fpgpio, "READBACK");
- expected = FPGPIO_BIT(4) | FPGPIO_BIT(0);
- if ((rb & expected) != expected)
- {
- ++failures;
- std::cout << "fail" << std::endl;
- if ((rb & FPGPIO_BIT(0)) == 0)
- std::cout << "Bit 0 should be set, but is not" << std::endl;
- if ((rb & FPGPIO_BIT(4)) == 0)
- std::cout << "Bit 4 should be set, but is not" << std::endl;
- } else {
- std::cout << "pass" << std::endl;
- }
- std::cout << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- usrp->set_gpio_attr(fpgpio, "OUT", 0, FPGPIO_BIT(4));
- if (stop_signal_called)
- break;
-
- // test ATR RX by receiving for 1 second
- std::cout << "\nTesting ATR RX output..." << std::flush;
- rx_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
- rx_stream->issue_stream_cmd(rx_cmd);
- stop_time = usrp->get_time_now() + dwell_time;
- while (not stop_signal_called and usrp->get_time_now() < stop_time)
- {
- try {
- rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
- } catch(...){}
- }
- rb = usrp->get_gpio_attr(fpgpio, "READBACK");
- expected = FPGPIO_BIT(1);
- if ((rb & expected) != expected)
- {
- ++failures;
- std::cout << "fail" << std::endl;
- std::cout << "Bit 1 should be set, but is not" << std::endl;
- } else {
- std::cout << "pass" << std::endl;
- }
- std::cout << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
- //clear out any data left in the rx stream
- try {
- rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
- } catch(...){}
- if (stop_signal_called)
- break;
-
- // test ATR TX by transmitting for 1 second
- std::cout << "\nTesting ATR TX output..." << std::flush;
- stop_time = usrp->get_time_now() + dwell_time;
- tx_md.start_of_burst = true;
- tx_md.end_of_burst = false;
- while (not stop_signal_called and usrp->get_time_now() < stop_time)
- {
- try {
- tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
- tx_md.start_of_burst = false;
- } catch(...){}
- }
- rb = usrp->get_gpio_attr(fpgpio, "READBACK");
- expected = FPGPIO_BIT(2);
- if ((rb & expected) != expected)
- {
- ++failures;
- std::cout << "fail" << std::endl;
- std::cout << "Bit 2 should be set, but is not" << std::endl;
- } else {
- std::cout << "pass" << std::endl;
- }
- std::cout << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- tx_md.end_of_burst = true;
- try {
- tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
- } catch(...){}
- if (stop_signal_called)
- break;
-
- // test ATR RX by transmitting and receiving for 1 second
- std::cout << "\nTesting ATR full duplex output..." << std::flush;
- rx_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
- rx_stream->issue_stream_cmd(rx_cmd);
- tx_md.start_of_burst = true;
- tx_md.end_of_burst = false;
- stop_time = usrp->get_time_now() + dwell_time;
- while (not stop_signal_called and usrp->get_time_now() < stop_time)
- {
- try {
- tx_stream->send(rx_buffs, nsamps_per_buff, tx_md, timeout);
- tx_md.start_of_burst = false;
- rx_stream->recv(tx_buffs, nsamps_per_buff, rx_md, timeout);
- } catch(...){}
- }
- rb = usrp->get_gpio_attr(fpgpio, "READBACK");
- expected = FPGPIO_BIT(3);
- if ((rb & expected) != expected)
- {
- ++failures;
- std::cout << "fail" << std::endl;
- std::cout << "Bit 3 should be set, but is not" << std::endl;
- } else {
- std::cout << "pass" << std::endl;
- }
- std::cout << std::endl;
- output_reg_values(fpgpio, usrp, num_bits);
- rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
- tx_md.end_of_burst = true;
- try {
- tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
- } catch(...){}
- //clear out any data left in the rx stream
- try {
- rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
- } catch(...){}
-
- std::cout << std::endl;
- if (failures)
- std::cout << failures << " tests failed" << std::endl;
- else
- std::cout << "All tests passed!" << std::endl;
-
- if (!vm.count("repeat"))
- break;
-
- std::cout << (boost::format("\nLoop %d completed") % ++loop) << std::endl;
- }
-
- //finished
- std::cout << std::endl << "Done!" << std::endl << std::endl;
-
- return EXIT_SUCCESS;
-}
diff --git a/host/examples/gpio.cpp b/host/examples/gpio.cpp
new file mode 100644
index 000000000..b0d15f35a
--- /dev/null
+++ b/host/examples/gpio.cpp
@@ -0,0 +1,462 @@
+//
+// Copyright 2014-15 Ettus Research LLC
+//
+// 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/>.
+//
+
+// Example for GPIO testing and bit banging.
+//
+// This example was originally designed to test the 11 bit wide front panel
+// GPIO on the X300 series and has since been adapted to work with any GPIO
+// bank on any USRP and provide optional bit banging. Please excuse the
+// clutter. Also, there is no current way to detect the width of the
+// specified GPIO bank, so the user must specify the width with the --bits
+// flag if more than 11 bits.
+//
+// GPIO Testing:
+// For testing, GPIO bits are set as follows:
+// GPIO[0] = ATR output 1 at idle
+// GPIO[1] = ATR output 1 during RX
+// GPIO[2] = ATR output 1 during TX
+// GPIO[3] = ATR output 1 during full duplex
+// GPIO[4] = output
+// GPIO[n:5] = input (all other pins)
+// The testing cycles through idle, TX, RX, and full duplex, dwelling on each
+// test case (default 2 seconds), and then comparing the readback register with
+// the expected values of the outputs for verification. The values of all GPIO
+// registers are displayed at the end of each test case. Outputs can be
+// physically looped back to inputs to manually verify the inputs.
+//
+// GPIO Bit Banging:
+// GPIO banks have the standard registers of DDR for data direction and OUT
+// for output values. Users can bit bang the GPIO bits by using this example
+// with the --bitbang flag and specifying the --ddr and --out flags to set the
+// values of the corresponding registers. The READBACK register is
+// continuously read for the duration of the dwell time (default 2 seconds) so
+// users can monitor changes on the inputs.
+//
+// Automatic Transmit/Receive (ATR):
+// In addition to the standard DDR and OUT registers, the GPIO banks also
+// have ATR (Automatic Transmit/Receive) control registers that allow the
+// GPIO pins to be automatically set to specific values when the USRP is
+// idle, transmitting, receiving, or operating in full duplex mode. The
+// description of these registers is below:
+// CTRL - Control (0=manual, 1=ATR)
+// ATR_0X - Values to be set when idle
+// ATR_RX - Output values to be set when receiving
+// 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).
+//
+// The UHD API
+// The multi_usrp::set_gpio_attr() method is the UHD API for configuring and
+// controlling the GPIO banks. The parameters to the method are:
+// 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")
+// 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).
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <uhd/convert.hpp>
+#include <boost/assign.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/thread.hpp>
+#include <csignal>
+#include <iostream>
+#include <stdlib.h>
+
+static const std::string GPIO_DEFAULT_CPU_FORMAT = "fc32";
+static const std::string GPIO_DEFAULT_OTW_FORMAT = "sc16";
+static const double GPIO_DEFAULT_RX_RATE = 500e3;
+static const double GPIO_DEFAULT_TX_RATE = 500e3;
+static const double GPIO_DEFAULT_DWELL_TIME = 2.0;
+static const std::string GPIO_DEFAULT_GPIO = "FP0";
+static const size_t GPIO_DEFAULT_NUM_BITS = 11;
+static const std::string GPIO_DEFAULT_CTRL = "0x0"; // all as user controlled
+static const std::string GPIO_DEFAULT_DDR = "0x0"; // all as inputs
+static const std::string GPIO_DEFAULT_OUT = "0x0";
+
+static UHD_INLINE boost::uint32_t GPIO_BIT(const size_t x)
+{
+ return (1 << x);
+}
+
+namespace po = boost::program_options;
+
+static bool stop_signal_called = false;
+void sig_int_handler(int){stop_signal_called = true;}
+
+std::string to_bit_string(boost::uint32_t val, const size_t num_bits)
+{
+ std::string out;
+ for (int i = num_bits - 1; i >= 0; i--)
+ {
+ std::string bit = ((val >> i) & 1) ? "1" : "0";
+ out += " ";
+ out += bit;
+ }
+ return out;
+}
+
+void output_reg_values(
+ const std::string bank,
+ const uhd::usrp::multi_usrp::sptr &usrp,
+ const size_t num_bits)
+{
+ std::vector<std::string> attrs = boost::assign::list_of("CTRL")("DDR")("ATR_0X")("ATR_RX")("ATR_TX")("ATR_XX")("OUT")("READBACK");
+ std::cout << (boost::format("%10s ") % "Bit");
+ for (int i = num_bits - 1; i >= 0; i--)
+ std::cout << (boost::format(" %2d") % i);
+ std::cout << std::endl;
+ BOOST_FOREACH(std::string &attr, attrs)
+ {
+ std::cout << (boost::format("%10s:%s")
+ % attr % to_bit_string(boost::uint32_t(usrp->get_gpio_attr(bank, attr)), num_bits))
+ << std::endl;
+ }
+}
+
+int UHD_SAFE_MAIN(int argc, char *argv[])
+{
+ uhd::set_thread_priority_safe();
+
+ //variables to be set by po
+ std::string args;
+ std::string cpu, otw;
+ double rx_rate, tx_rate, dwell;
+ std::string gpio;
+ size_t num_bits;
+ std::string ctrl_str;
+ std::string ddr_str;
+ std::string out_str;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "multi uhd device address args")
+ ("repeat", "repeat loop until Ctrl-C is pressed")
+ ("cpu", po::value<std::string>(&cpu)->default_value(GPIO_DEFAULT_CPU_FORMAT), "cpu data format")
+ ("otw", po::value<std::string>(&otw)->default_value(GPIO_DEFAULT_OTW_FORMAT), "over the wire data format")
+ ("rx_rate", po::value<double>(&rx_rate)->default_value(GPIO_DEFAULT_RX_RATE), "rx sample rate")
+ ("tx_rate", po::value<double>(&tx_rate)->default_value(GPIO_DEFAULT_TX_RATE), "tx sample rate")
+ ("dwell", po::value<double>(&dwell)->default_value(GPIO_DEFAULT_DWELL_TIME), "dwell time in seconds for each test case")
+ ("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")
+ ("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")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("gpio %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
+ std::cout << boost::format("Using Device: %s") % usrp->get_pp_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);
+
+ //configure GPIO registers
+ boost::uint32_t ddr = strtoul(ddr_str.c_str(), NULL, 0);
+ boost::uint32_t out = strtoul(out_str.c_str(), NULL, 0);
+ boost::uint32_t ctrl = 0;
+ boost::uint32_t atr_idle = 0;
+ boost::uint32_t atr_rx = 0;
+ boost::uint32_t atr_tx = 0;
+ boost::uint32_t atr_duplex = 0;
+ boost::uint32_t mask = (1 << num_bits) - 1;
+
+ if (!vm.count("bitbang"))
+ {
+ //set up GPIO outputs:
+ //GPIO[0] = ATR output 1 at idle
+ ctrl |= GPIO_BIT(0);
+ atr_idle |= GPIO_BIT(0);
+ ddr |= GPIO_BIT(0);
+
+ //GPIO[1] = ATR output 1 during RX
+ ctrl |= GPIO_BIT(1);
+ ddr |= GPIO_BIT(1);
+ atr_rx |= GPIO_BIT(1);
+
+ //GPIO[2] = ATR output 1 during TX
+ ctrl |= GPIO_BIT(2);
+ ddr |= GPIO_BIT(2);
+ atr_tx |= GPIO_BIT(2);
+
+ //GPIO[3] = ATR output 1 during full duplex
+ ctrl |= GPIO_BIT(3);
+ ddr |= GPIO_BIT(3);
+ atr_duplex |= GPIO_BIT(3);
+
+ //GPIO[4] = output
+ ddr |= GPIO_BIT(4);
+ }
+
+ //set data direction register (DDR)
+ usrp->set_gpio_attr(gpio, "DDR", ddr, mask);
+
+ //set output values (OUT)
+ usrp->set_gpio_attr(gpio, "OUT", out, mask);
+
+ //set ATR registers
+ usrp->set_gpio_attr(gpio, "ATR_0X", atr_idle, mask);
+ usrp->set_gpio_attr(gpio, "ATR_RX", atr_rx, mask);
+ usrp->set_gpio_attr(gpio, "ATR_TX", atr_tx, mask);
+ usrp->set_gpio_attr(gpio, "ATR_XX", atr_duplex, mask);
+
+ //set control register
+ usrp->set_gpio_attr(gpio, "CTRL", ctrl, mask);
+
+ //print out initial state of FP GPIO
+ std::cout << "\nConfigured GPIO values:" << std::endl;
+ output_reg_values(gpio, usrp, num_bits);
+ std::cout << std::endl;
+
+ //set up streams
+ uhd::stream_args_t rx_args(cpu, otw);
+ uhd::stream_args_t tx_args(cpu, otw);
+ uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(rx_args);
+ uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(tx_args);
+ uhd::stream_cmd_t rx_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ rx_cmd.stream_now = true;
+ usrp->set_rx_rate(rx_rate);
+ usrp->set_tx_rate(tx_rate);
+
+ //set up buffers for tx and rx
+ const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
+ const size_t nsamps_per_buff = max_samps_per_packet;
+ std::vector<char> rx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu));
+ std::vector<char> tx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu));
+ std::vector<void *> rx_buffs, tx_buffs;
+ for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++)
+ rx_buffs.push_back(&rx_buff.front()); //same buffer for each channel
+ for (size_t ch = 0; ch < tx_stream->get_num_channels(); ch++)
+ tx_buffs.push_back(&tx_buff.front()); //same buffer for each channel
+
+ uhd::rx_metadata_t rx_md;
+ uhd::tx_metadata_t tx_md;
+ tx_md.has_time_spec = false;
+ tx_md.start_of_burst = true;
+ uhd::time_spec_t stop_time;
+ double timeout = 0.01;
+ uhd::time_spec_t dwell_time(dwell);
+ int loop = 0;
+ boost::uint32_t rb, expected;
+
+ //register signal handler
+ std::signal(SIGINT, &sig_int_handler);
+
+ if (!vm.count("bitbang"))
+ {
+ // Test the mask parameter of the multi_usrp::set_gpio_attr API
+ // We only need to test once with no dwell time
+ std::cout << "\nTesting mask..." << std::flush;
+ //send a value of all 1's to the DDR with a mask for only upper most bit
+ usrp->set_gpio_attr(gpio, "DDR", ~0, GPIO_BIT(num_bits - 1));
+ //upper most bit should now be 1, but all the other bits should be unchanged
+ rb = usrp->get_gpio_attr(gpio, "DDR") & mask;
+ expected = ddr | GPIO_BIT(num_bits - 1);
+ if (rb == expected)
+ std::cout << "pass:" << std::endl;
+ else
+ std::cout << "fail:" << std::endl;
+ output_reg_values(gpio, usrp, num_bits);
+ //restore DDR value
+ usrp->set_gpio_attr(gpio, "DDR", ddr, mask);
+ }
+
+ while (not stop_signal_called)
+ {
+ int failures = 0;
+
+ if (vm.count("repeat"))
+ std::cout << "Press Ctrl + C to quit..." << std::endl;
+
+ if (vm.count("bitbang"))
+ {
+ // dwell and continuously read back GPIO values
+ stop_time = usrp->get_time_now() + dwell_time;
+ while (not stop_signal_called and usrp->get_time_now() < stop_time)
+ {
+ rb = usrp->get_gpio_attr(gpio, "READBACK");
+ std::cout << "\rREADBACK: " << to_bit_string(rb, num_bits);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
+ }
+ std::cout << std::endl;
+ }
+ else
+ {
+ // test user controlled GPIO and ATR idle by setting bit 4 high for 1 second
+ std::cout << "\nTesting user controlled GPIO and ATR idle output..." << std::flush;
+ usrp->set_gpio_attr(gpio, "OUT", 1 << 4, 1 << 4);
+ stop_time = usrp->get_time_now() + dwell_time;
+ while (not stop_signal_called and usrp->get_time_now() < stop_time)
+ {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+ rb = usrp->get_gpio_attr(gpio, "READBACK");
+ expected = GPIO_BIT(4) | GPIO_BIT(0);
+ if ((rb & expected) != expected)
+ {
+ ++failures;
+ std::cout << "fail:" << std::endl;
+ if ((rb & GPIO_BIT(0)) == 0)
+ std::cout << "Bit 0 should be set, but is not" << std::endl;
+ if ((rb & GPIO_BIT(4)) == 0)
+ std::cout << "Bit 4 should be set, but is not" << std::endl;
+ } else {
+ std::cout << "pass:" << std::endl;
+ }
+ output_reg_values(gpio, usrp, num_bits);
+ usrp->set_gpio_attr(gpio, "OUT", 0, GPIO_BIT(4));
+ if (stop_signal_called)
+ break;
+
+ // test ATR RX by receiving for 1 second
+ std::cout << "\nTesting ATR RX output..." << std::flush;
+ rx_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
+ rx_stream->issue_stream_cmd(rx_cmd);
+ stop_time = usrp->get_time_now() + dwell_time;
+ while (not stop_signal_called and usrp->get_time_now() < stop_time)
+ {
+ try {
+ rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
+ } catch(...){}
+ }
+ rb = usrp->get_gpio_attr(gpio, "READBACK");
+ expected = GPIO_BIT(1);
+ if ((rb & expected) != expected)
+ {
+ ++failures;
+ std::cout << "fail:" << std::endl;
+ std::cout << "Bit 1 should be set, but is not" << std::endl;
+ } else {
+ std::cout << "pass:" << std::endl;
+ }
+ output_reg_values(gpio, usrp, num_bits);
+ rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+ //clear out any data left in the rx stream
+ try {
+ rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
+ } catch(...){}
+ if (stop_signal_called)
+ break;
+
+ // test ATR TX by transmitting for 1 second
+ std::cout << "\nTesting ATR TX output..." << std::flush;
+ stop_time = usrp->get_time_now() + dwell_time;
+ tx_md.start_of_burst = true;
+ tx_md.end_of_burst = false;
+ while (not stop_signal_called and usrp->get_time_now() < stop_time)
+ {
+ try {
+ tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
+ tx_md.start_of_burst = false;
+ } catch(...){}
+ }
+ rb = usrp->get_gpio_attr(gpio, "READBACK");
+ expected = GPIO_BIT(2);
+ if ((rb & expected) != expected)
+ {
+ ++failures;
+ std::cout << "fail:" << std::endl;
+ std::cout << "Bit 2 should be set, but is not" << std::endl;
+ } else {
+ std::cout << "pass:" << std::endl;
+ }
+ output_reg_values(gpio, usrp, num_bits);
+ tx_md.end_of_burst = true;
+ try {
+ tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
+ } catch(...){}
+ if (stop_signal_called)
+ break;
+
+ // test ATR RX by transmitting and receiving for 1 second
+ std::cout << "\nTesting ATR full duplex output..." << std::flush;
+ rx_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
+ rx_stream->issue_stream_cmd(rx_cmd);
+ tx_md.start_of_burst = true;
+ tx_md.end_of_burst = false;
+ stop_time = usrp->get_time_now() + dwell_time;
+ while (not stop_signal_called and usrp->get_time_now() < stop_time)
+ {
+ try {
+ tx_stream->send(rx_buffs, nsamps_per_buff, tx_md, timeout);
+ tx_md.start_of_burst = false;
+ rx_stream->recv(tx_buffs, nsamps_per_buff, rx_md, timeout);
+ } catch(...){}
+ }
+ rb = usrp->get_gpio_attr(gpio, "READBACK");
+ expected = GPIO_BIT(3);
+ if ((rb & expected) != expected)
+ {
+ ++failures;
+ std::cout << "fail:" << std::endl;
+ std::cout << "Bit 3 should be set, but is not" << std::endl;
+ } else {
+ std::cout << "pass:" << std::endl;
+ }
+ output_reg_values(gpio, usrp, num_bits);
+ rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+ tx_md.end_of_burst = true;
+ try {
+ tx_stream->send(tx_buffs, nsamps_per_buff, tx_md, timeout);
+ } catch(...){}
+ //clear out any data left in the rx stream
+ try {
+ rx_stream->recv(rx_buffs, nsamps_per_buff, rx_md, timeout);
+ } catch(...){}
+
+ std::cout << std::endl;
+ if (failures)
+ std::cout << failures << " tests failed" << std::endl;
+ else
+ std::cout << "All tests passed!" << std::endl;
+ }
+
+ if (!vm.count("repeat"))
+ break;
+
+ if (not stop_signal_called)
+ std::cout << (boost::format("\nLoop %d completed") % ++loop) << std::endl;
+ }
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return EXIT_SUCCESS;
+}
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 663696926..89af6a6e1 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2012-2014 Ettus Research LLC
+// Copyright 2012-2015 Ettus Research LLC
//
// 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
@@ -529,6 +529,19 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
_tree->create<std::vector<std::string> >(mb_path / "clock_source" / "options").set(clock_sources);
////////////////////////////////////////////////////////////////////
+ // front panel gpio
+ ////////////////////////////////////////////////////////////////////
+ _radio_perifs[0].fp_gpio = gpio_core_200::make(_radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO);
+ BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)
+ {
+ _tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / attr.second)
+ .set(0)
+ .subscribe(boost::bind(&b200_impl::set_fp_gpio, this, _radio_perifs[0].fp_gpio, attr.first, _1));
+ }
+ _tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / "READBACK")
+ .publish(boost::bind(&b200_impl::get_fp_gpio, this, _radio_perifs[0].fp_gpio));
+
+ ////////////////////////////////////////////////////////////////////
// dboard eeproms but not really
////////////////////////////////////////////////////////////////////
dboard_eeprom_t db_eeprom;
@@ -902,6 +915,26 @@ void b200_impl::set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &mb_eeprom)
}
+boost::uint32_t b200_impl::get_fp_gpio(gpio_core_200::sptr gpio)
+{
+ return boost::uint32_t(gpio->read_gpio(dboard_iface::UNIT_RX));
+}
+
+void b200_impl::set_fp_gpio(gpio_core_200::sptr gpio, const gpio_attr_t attr, const boost::uint32_t value)
+{
+ switch (attr)
+ {
+ case CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value);
+ case DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value);
+ case OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value);
+ case ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value);
+ case ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value);
+ case ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value);
+ case ATR_XX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value);
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
/***********************************************************************
* Reference time and clock
**********************************************************************/
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index 64d7aa7d0..cff767b4b 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2012-2015 Ettus Research LLC
//
// 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
@@ -156,6 +156,7 @@ private:
{
radio_ctrl_core_3000::sptr ctrl;
gpio_core_200_32wo::sptr atr;
+ gpio_core_200::sptr fp_gpio;
time_core_3000::sptr time64;
rx_vita_core_3000::sptr framer;
rx_dsp_core_3000::sptr ddc;
@@ -194,6 +195,9 @@ private:
void update_enables(void);
void update_atrs(void);
+ boost::uint32_t get_fp_gpio(gpio_core_200::sptr);
+ void set_fp_gpio(gpio_core_200::sptr, const gpio_attr_t, const boost::uint32_t);
+
double _tick_rate;
double get_tick_rate(void){return _tick_rate;}
double set_tick_rate(const double rate);
@@ -245,6 +249,7 @@ private:
//! Coercer, attached to the "rate/value" property on the rx dsps.
double coerce_rx_samp_rate(rx_dsp_core_3000::sptr, size_t, const double);
void update_rx_samp_rate(const size_t, const double);
+
//! Coercer, attached to the "rate/value" property on the tx dsps.
double coerce_tx_samp_rate(tx_dsp_core_3000::sptr, size_t, const double);
void update_tx_samp_rate(const size_t, const double);
diff --git a/host/lib/usrp/b200/b200_regs.hpp b/host/lib/usrp/b200/b200_regs.hpp
index 900651f94..8f2dd03f3 100644
--- a/host/lib/usrp/b200/b200_regs.hpp
+++ b/host/lib/usrp/b200/b200_regs.hpp
@@ -46,11 +46,13 @@ localparam SR_TX_DSP = 184;
localparam SR_TIME = 128;
localparam SR_RX_FMT = 136;
localparam SR_TX_FMT = 138;
+localparam SR_FP_GPIO = 200;
localparam RB32_TEST = 0;
localparam RB64_TIME_NOW = 8;
localparam RB64_TIME_PPS = 16;
localparam RB64_CODEC_READBACK = 24;
+localparam RB32_FP_GPIO = 32;
//pll constants
static const int AD9361_SLAVENO = (1 << 0);
diff --git a/host/lib/usrp/cores/gpio_core_200.hpp b/host/lib/usrp/cores/gpio_core_200.hpp
index 164437f40..a76cced01 100644
--- a/host/lib/usrp/cores/gpio_core_200.hpp
+++ b/host/lib/usrp/cores/gpio_core_200.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2011,2014 Ettus Research LLC
+// Copyright 2011,2014,2015 Ettus Research LLC
//
// 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
@@ -20,10 +20,17 @@
#include <uhd/config.hpp>
#include <uhd/usrp/dboard_iface.hpp>
+#include <boost/assign.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <uhd/types/wb_iface.hpp>
+#include <map>
+
+typedef enum{CTRL,DDR,OUT,ATR_0X,ATR_RX,ATR_TX,ATR_XX} gpio_attr_t;
+typedef std::map<gpio_attr_t,std::string> gpio_attr_map_t;
+static const gpio_attr_map_t gpio_attr_map =
+ boost::assign::map_list_of(CTRL,"CTRL")(DDR,"DDR")(OUT,"OUT")(ATR_0X,"ATR_0X")(ATR_RX,"ATR_RX")(ATR_TX,"ATR_TX")(ATR_XX,"ATR_XX");
class gpio_core_200 : boost::noncopyable{
public:
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index ce94147e8..ac92f9a12 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -469,15 +469,14 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
// internal gpios
////////////////////////////////////////////////////////////////////
gpio_core_200::sptr fp_gpio = gpio_core_200::make(_radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO);
- const std::vector<std::string> gpio_attrs = boost::assign::list_of("CTRL")("DDR")("OUT")("ATR_0X")("ATR_RX")("ATR_TX")("ATR_XX");
- BOOST_FOREACH(const std::string &attr, gpio_attrs)
+ BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)
{
- _tree->create<boost::uint32_t>(mb_path / "gpio" / "INT0" / attr)
- .subscribe(boost::bind(&e300_impl::_set_internal_gpio, this, fp_gpio, attr, _1))
+ _tree->create<boost::uint32_t>(mb_path / "gpio" / "INT0" / attr.second)
+ .subscribe(boost::bind(&e300_impl::_set_internal_gpio, this, fp_gpio, attr.first, _1))
.set(0);
}
_tree->create<boost::uint8_t>(mb_path / "gpio" / "INT0" / "READBACK")
- .publish(boost::bind(&e300_impl::_get_internal_gpio, this, fp_gpio, "READBACK"));
+ .publish(boost::bind(&e300_impl::_get_internal_gpio, this, fp_gpio));
////////////////////////////////////////////////////////////////////
@@ -576,32 +575,35 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr)
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_spec);
}
-boost::uint8_t e300_impl::_get_internal_gpio(
- gpio_core_200::sptr gpio,
- const std::string &)
+boost::uint8_t e300_impl::_get_internal_gpio(gpio_core_200::sptr gpio)
{
return boost::uint32_t(gpio->read_gpio(dboard_iface::UNIT_RX));
}
void e300_impl::_set_internal_gpio(
gpio_core_200::sptr gpio,
- const std::string &attr,
+ const gpio_attr_t attr,
const boost::uint32_t value)
{
- if (attr == "CTRL")
+ switch (attr)
+ {
+ case CTRL:
return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value);
- else if (attr == "DDR")
+ case DDR:
return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value);
- else if (attr == "OUT")
+ case OUT:
return gpio->set_gpio_out(dboard_iface::UNIT_RX, value);
- else if (attr == "ATR_0X")
+ case ATR_0X:
return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value);
- else if (attr == "ATR_RX")
+ case ATR_RX:
return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value);
- else if (attr == "ATR_TX")
+ case ATR_TX:
return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value);
- else if (attr == "ATR_XX")
+ case ATR_XX:
return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value);
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ }
}
uhd::sensor_value_t e300_impl::_get_fe_pll_lock(const bool is_tx)
diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp
index c7d683f58..21aef215d 100644
--- a/host/lib/usrp/e300/e300_impl.hpp
+++ b/host/lib/usrp/e300/e300_impl.hpp
@@ -264,13 +264,11 @@ private: // methods
uhd::sensor_value_t _get_fe_pll_lock(const bool is_tx);
// internal gpios
- boost::uint8_t _get_internal_gpio(
- gpio_core_200::sptr,
- const std::string &);
+ boost::uint8_t _get_internal_gpio(gpio_core_200::sptr);
void _set_internal_gpio(
gpio_core_200::sptr gpio,
- const std::string &attr,
+ const gpio_attr_t attr,
const boost::uint32_t value);
private: // members
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index bf676b661..a82be543d 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2013-2014 Ettus Research LLC
+// Copyright 2013-2015 Ettus Research LLC
//
// 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
@@ -695,15 +695,14 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
// front panel gpio
////////////////////////////////////////////////////////////////////
mb.fp_gpio = gpio_core_200::make(mb.radio_perifs[0].ctrl, TOREG(SR_FP_GPIO), RB32_FP_GPIO);
- const std::vector<std::string> GPIO_ATTRS = boost::assign::list_of("CTRL")("DDR")("OUT")("ATR_0X")("ATR_RX")("ATR_TX")("ATR_XX");
- BOOST_FOREACH(const std::string &attr, GPIO_ATTRS)
+ BOOST_FOREACH(const gpio_attr_map_t::value_type attr, gpio_attr_map)
{
- _tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / attr)
+ _tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / attr.second)
.set(0)
- .subscribe(boost::bind(&x300_impl::set_fp_gpio, this, mb.fp_gpio, attr, _1));
+ .subscribe(boost::bind(&x300_impl::set_fp_gpio, this, mb.fp_gpio, attr.first, _1));
}
_tree->create<boost::uint32_t>(mb_path / "gpio" / "FP0" / "READBACK")
- .publish(boost::bind(&x300_impl::get_fp_gpio, this, mb.fp_gpio, "READBACK"));
+ .publish(boost::bind(&x300_impl::get_fp_gpio, this, mb.fp_gpio));
////////////////////////////////////////////////////////////////////
// register the time keepers - only one can be the highlander
@@ -1353,7 +1352,7 @@ void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb)
void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source)
{
//Optimize for the case when the current source is internal and we are trying
- //to set it to internal. This is the only case where we are guaranteed that
+ //to set it to internal. This is the only case where we are guaranteed that
//the clock has not gone away so we can skip setting the MUX and reseting the LMK.
if (not (mb.current_refclk_src == "internal" and source == "internal")) {
//Update the clock MUX on the motherboard to select the requested source
@@ -1534,20 +1533,24 @@ void x300_impl::set_mb_eeprom(i2c_iface::sptr i2c, const mboard_eeprom_t &mb_eep
* front-panel GPIO
**********************************************************************/
-boost::uint32_t x300_impl::get_fp_gpio(gpio_core_200::sptr gpio, const std::string &)
+boost::uint32_t x300_impl::get_fp_gpio(gpio_core_200::sptr gpio)
{
return boost::uint32_t(gpio->read_gpio(dboard_iface::UNIT_RX));
}
-void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const std::string &attr, const boost::uint32_t value)
+void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const gpio_attr_t attr, const boost::uint32_t value)
{
- if (attr == "CTRL") return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value);
- if (attr == "DDR") return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value);
- if (attr == "OUT") return gpio->set_gpio_out(dboard_iface::UNIT_RX, value);
- if (attr == "ATR_0X") return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value);
- if (attr == "ATR_RX") return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value);
- if (attr == "ATR_TX") return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value);
- if (attr == "ATR_XX") return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value);
+ switch (attr)
+ {
+ case CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value);
+ case DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value);
+ case OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value);
+ case ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value);
+ case ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value);
+ case ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value);
+ case ATR_XX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value);
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
}
/***********************************************************************
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 70c5dccb4..9ad060c85 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -1,5 +1,5 @@
//
-// Copyright 2013-2014 Ettus Research LLC
+// Copyright 2013-2015 Ettus Research LLC
//
// 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
@@ -360,8 +360,8 @@ private:
void check_fpga_compat(const uhd::fs_path &mb_path, uhd::wb_iface::sptr iface);
void update_atr_leds(gpio_core_200_32wo::sptr, const std::string &ant);
- boost::uint32_t get_fp_gpio(gpio_core_200::sptr, const std::string &);
- void set_fp_gpio(gpio_core_200::sptr, const std::string &, const boost::uint32_t);
+ boost::uint32_t get_fp_gpio(gpio_core_200::sptr);
+ void set_fp_gpio(gpio_core_200::sptr, const gpio_attr_t, const boost::uint32_t);
//**PRECONDITION**
//This function assumes that all the VITA times in "radios" are synchronized