From 91347ea2cbf7618d4439548210eec940c582cbb8 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 8 Oct 2014 14:44:49 +0200 Subject: uhd: Added sid_t This is a data type to represent SIDs (stream IDs). It includes setters and getters for all components of the SID, converters to and from string and uint32 as well as C++ streams. --- host/lib/types/CMakeLists.txt | 1 + host/lib/types/sid.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 host/lib/types/sid.cpp (limited to 'host/lib') diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index f19043c1e..853da3fe2 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -86,6 +86,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp ${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/time_spec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tune.cpp ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp diff --git a/host/lib/types/sid.cpp b/host/lib/types/sid.cpp new file mode 100644 index 000000000..2fc3781cf --- /dev/null +++ b/host/lib/types/sid.cpp @@ -0,0 +1,153 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +sid_t::sid_t() + : _sid(0x0000), _set(false) +{ +} + +sid_t::sid_t(boost::uint32_t sid) + : _sid(sid), _set(true) +{ +} + +sid_t::sid_t(boost::uint8_t src_addr, boost::uint8_t src_ep, boost::uint8_t dst_addr, boost::uint8_t dst_ep) + : _sid(0x0000), _set(true) +{ + set_src_addr(src_addr); + set_src_endpoint(src_ep); + set_dst_addr(dst_addr); + set_dst_endpoint(dst_ep); +} + +sid_t::sid_t(const std::string &sid_str) + : _sid(0x0000), _set(false) +{ + set_from_str(sid_str); +} + +std::string sid_t::to_pp_string() const +{ + if (not _set) { + return "x.x>x.x"; + } + return str(boost::format("%d.%d>%d.%d") + % get_src_addr() + % get_src_endpoint() + % get_dst_addr() + % get_dst_endpoint() + ); +} + +std::string sid_t::to_pp_string_hex() const +{ + if (not _set) { + return "xx:xx>xx:xx"; + } + return str(boost::format("%02x:%02x>%02x:%02x") + % get_src_addr() + % get_src_endpoint() + % get_dst_addr() + % get_dst_endpoint() + ); +} + + +void sid_t::set_sid(boost::uint32_t new_sid) +{ + _set = true; + _sid = new_sid; +} + +void sid_t::set_from_str(const std::string &sid_str) +{ + const std::string dec_regex = "(\\d{1,3})\\.(\\d{1,3})[.:/><](\\d{1,3})\\.(\\d{1,3})"; + const std::string hex_regex = "([[:xdigit:]]{2}):([[:xdigit:]]{2})[.:/><]([[:xdigit:]]{2}):([[:xdigit:]]{2})"; + + boost::cmatch matches; + if (boost::regex_match(sid_str.c_str(), matches, boost::regex(dec_regex))) { + set_src_addr(boost::lexical_cast(matches[1])); + set_src_endpoint(boost::lexical_cast(matches[2])); + set_dst_addr(boost::lexical_cast(matches[3])); + set_dst_endpoint(boost::lexical_cast(matches[4])); + return; + } + + if (boost::regex_match(sid_str.c_str(), matches, boost::regex(hex_regex))) { + set_src_addr(uhd::cast::hexstr_cast(matches[1])); + set_src_endpoint(uhd::cast::hexstr_cast(matches[2])); + set_dst_addr(uhd::cast::hexstr_cast(matches[3])); + set_dst_endpoint(uhd::cast::hexstr_cast(matches[4])); + return; + } + + throw uhd::value_error(str(boost::format("Invalid SID representation: %s") % sid_str)); +} + +void sid_t::set_src(boost::uint32_t new_addr) { + set_sid((_sid & 0x0000FFFF) | ((new_addr & 0xFFFF) << 16)); +} + +void sid_t::set_dst(boost::uint32_t new_addr) { + set_sid((_sid & 0xFFFF0000) | (new_addr & 0xFFFF)); +} + +void sid_t::set_src_addr(boost::uint32_t new_addr) { + set_sid((_sid & 0x00FFFFFF) | ((new_addr & 0xFF) << 24)); +} + +void sid_t::set_src_endpoint(boost::uint32_t new_addr) { + set_sid((_sid & 0xFF00FFFF) | ((new_addr & 0xFF) << 16)); +} + +void sid_t::set_dst_addr(boost::uint32_t new_addr) { + set_sid((_sid & 0xFFFF00FF) | ((new_addr & 0xFF) << 8)); +} + +void sid_t::set_dst_endpoint(boost::uint32_t new_addr) { + set_sid((_sid & 0xFFFFFF00) | ((new_addr & 0xFF) << 0)); +} + +void sid_t::set_dst_xbarport(boost::uint32_t new_xbarport) +{ + set_sid((_sid & 0xFFFFFF0F) | ((new_xbarport & 0xF) << 4)); +} + +void sid_t::set_dst_blockport(boost::uint32_t new_blockport) +{ + set_sid((_sid & 0xFFFFFFF0) | ((new_blockport & 0xF) << 0)); +} + +sid_t sid_t::reversed() +{ + return sid_t((get_dst() << 16) | get_src()); +} + +void sid_t::reverse() +{ + set_sid((get_dst() << 16) | get_src()); +} + -- cgit v1.2.3 From 95aa5da3baf236cf5f2ead03d55710e8699a87b2 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 4 Nov 2014 15:17:43 +0100 Subject: x300: Fixed typo in io_impl --- host/lib/usrp/x300/x300_io_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index 500a24f7f..c5b8f49e3 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -532,7 +532,7 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) //setup defaults for unspecified values if (not args.otw_format.empty() and args.otw_format != "sc16") { - throw uhd::value_error("x300_impl::get_rx_stream only supports otw_format sc16"); + throw uhd::value_error("x300_impl::get_tx_stream only supports otw_format sc16"); } args.otw_format = "sc16"; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; -- cgit v1.2.3 From 265db795c26cf9609f8f1288484f85788cbf7b3d Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Thu, 6 Nov 2014 14:21:39 -0800 Subject: x300: Cleaned up DAC ctrl and clock init logic - DAC: Squashed configuration into 2 main operations: reset and reset_and_resync - DAC: Put in sleep mode during configuration - DAC: Synchronize only if streaming to more than one DAC - DAC: Use falling edge sync mode - DAC: Fixed power up/down settings - DAC: Frontend sync failure is fatal - Clocks: Refactored clock source change logic - Clocks: Cleaned up init and lock-check sequence --- host/lib/usrp/x300/x300_clock_ctrl.cpp | 1 - host/lib/usrp/x300/x300_dac_ctrl.cpp | 210 +++++++++++++++++-------- host/lib/usrp/x300/x300_dac_ctrl.hpp | 14 +- host/lib/usrp/x300/x300_impl.cpp | 273 ++++++++++++++++++--------------- host/lib/usrp/x300/x300_impl.hpp | 12 +- host/lib/usrp/x300/x300_io_impl.cpp | 9 +- 6 files changed, 318 insertions(+), 201 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp index 21411e651..247c10ac4 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp @@ -49,7 +49,6 @@ x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface, _master_clock_rate(master_clock_rate), _system_ref_rate(system_ref_rate) { - set_master_clock_rate(master_clock_rate); } void reset_clocks() { diff --git a/host/lib/usrp/x300/x300_dac_ctrl.cpp b/host/lib/usrp/x300/x300_dac_ctrl.cpp index 62fe55c35..d3bcb8644 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.cpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.cpp @@ -25,6 +25,8 @@ #include #include //sleep +#define X300_DAC_FRONTEND_SYNC_FAILURE_FATAL + using namespace uhd; #define write_ad9146_reg(addr, data) \ @@ -45,19 +47,68 @@ public: x300_dac_ctrl_impl(uhd::spi_iface::sptr iface, const size_t slaveno, const double refclk): _iface(iface), _slaveno(slaveno), _refclk(refclk) { - init(); - check_pll(); + //Power up all DAC subsystems + write_ad9146_reg(0x01, 0x10); //Up: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg(0x02, 0x00); //No extended delays. Up: Voltage Ref, PLL, DAC, FIFO, Filters + + reset(); } - void init() + ~x300_dac_ctrl_impl(void) { - write_ad9146_reg(0x00, 0x20); // Take DAC into reset. - write_ad9146_reg(0x00, 0x80); // Enable SPI reads and come out of reset - write_ad9146_reg(0x1e, 0x01); // Data path config - set for proper operation + UHD_SAFE_CALL + ( + //Power down all DAC subsystems + write_ad9146_reg(0x01, 0xEF); //Down: I DAC, Q DAC, Receiver, Voltage Ref, Clocks + write_ad9146_reg(0x02, 0x1F); //No extended delays. Down: Voltage Ref, PLL, DAC, FIFO, Filters + ) + } + + void reset() + { + //ADI recommendations: + //- soft reset the chip before configuration + //- put the chip in sleep mode during configuration and wake it up when done + _soft_reset(); + _sleep_mode(true); + _init(); + _sleep_mode(false); + } + + void reset_and_resync() + { + //ADI recommendations: + //- soft reset the chip before configuration + //- put the chip in sleep mode during configuration and wake it up when done + //- configure synchronization settings when sleeping + _soft_reset(); + _sleep_mode(true); + _init(); + _backend_sync(); + _sleep_mode(false); + } + + void verify_sync() + { + _check_pll(); + _check_dac_sync(); +#ifdef X300_DAC_FRONTEND_SYNC_FAILURE_FATAL + _check_frontend_sync(true); +#else + _check_frontend_sync(false); +#endif + } + + // + // Setup all non-synchronization related DAC parameters + // + void _init() + { + write_ad9146_reg(0x1e, 0x01); //Datasheet: "Set 1 for proper operation" + write_ad9146_reg(0x06, 0xFF); //Clear all event flags // Calculate N0 to be VCO friendly. // Aim for VCO between 1 and 2GHz, assert otherwise. - // const int N1 = 4; const int N1 = 4; int N0_val, N0; for (N0_val = 0; N0_val < 3; N0_val++) @@ -68,78 +119,83 @@ public: UHD_ASSERT_THROW((_refclk * N0 * N1) >= 1e9); UHD_ASSERT_THROW((_refclk * N0 * N1) <= 2e9); - /* Start PLL */ - //write_ad9146_reg(0x0C, 0xD1); // Narrow PLL loop filter, Midrange charge pump. + // Start PLL + write_ad9146_reg(0x06, 0xC0); //Clear PLL event flags + write_ad9146_reg(0x0C, 0xD1); // Narrow PLL loop filter, Midrange charge pump. write_ad9146_reg(0x0D, 0xD1 | (N0_val << 2)); // N1=4, N2=16, N0 as calculated - //write_ad9146_reg(0x0D, 0x90 | (N0_val << 2)); // N1=2, N2=8, N0 as calculated write_ad9146_reg(0x0A, 0xCF); // Auto init VCO band training as per datasheet write_ad9146_reg(0x0A, 0xA0); // See above. - /* Skew DCI signal to find stable data eye */ - //write_ad9146_reg(0x16, 0x04); //Disable delay in DCI - //write_ad9146_reg(0x16, 0x00); //165ps delay in DCI - //write_ad9146_reg(0x16, 0x01); //375ps delay in DCI - write_ad9146_reg(0x16, 0x02); //615ps delay in DCI - //write_ad9146_reg(0x16, 0x03); //720ps delay in DCI + _check_pll(); + // Configure digital interface settings + write_ad9146_reg(0x16, 0x02); // Skew DCI signal by 615ps to find stable data eye write_ad9146_reg(0x03, 0x00); // 2's comp, I first, byte wide interface - //fpga wants I,Q in the sample word: //first transaction goes into low bits //second transaction goes into high bits //therefore, we want Q to go first (bit 6 == 1) write_ad9146_reg(0x03, (1 << 6)); //2s comp, i first, byte mode - write_ad9146_reg(0x10, 0x48); // Disable SYNC mode. - - // FIFO write pointer offset - // It was found that the read was happening before the write - // so the FIFO was maintainining a depth of 3 during operation. - // Setting it to 5 to ensure it maintains the ideal depth of 4. - // TODO: Investigate RefClk -> DCI clock timing. - write_ad9146_reg(0x17, 0x05); - - write_ad9146_reg(0x18, 0x02); // Request soft FIFO align - write_ad9146_reg(0x18, 0x00); // (See above) - write_ad9146_reg(0x1B, 0xE4); // Bypass: Modulator, InvSinc, IQ Bal - - /* Configure interpolation filters */ + // Configure interpolation filters write_ad9146_reg(0x1C, 0x00); // Configure HB1 write_ad9146_reg(0x1D, 0x00); // Configure HB2 + write_ad9146_reg(0x1B, 0xE4); // Bypass: Modulator, InvSinc, IQ Bal - // Clear event flags - write_ad9146_reg(0x06, 0xFF); - } - - - ~x300_dac_ctrl_impl(void) - { - UHD_SAFE_CALL - ( - write_ad9146_reg(0x1, 0xf); //total power down - write_ad9146_reg(0x2, 0xf); //total power down - ) + // Disable sync mode by default (may get turned on later) + write_ad9146_reg(0x10, 0x40); // Disable SYNC mode. } - void arm_dac_sync(void) + // + // Attempt to synchronize AD9146's + // + void _backend_sync(void) { - // - // Attempt to synchronize AD9146's - // - write_ad9146_reg(0x10, 0x48); // Disable SYNC mode. + write_ad9146_reg(0x10, 0x40); // Disable SYNC mode to reset state machines. write_ad9146_reg(0x06, 0x30); // Clear Sync event flags - write_ad9146_reg(0x10, 0xCF); // Enable SYNC mode. Sync Averaging set to 128. - } - void reset() - { - init(); + //SYNC Settings: + //- SYNC = Enabled + //- Data Rate Mode: Synchronize at the rate at which data is consumed and not at + // the granularity of the FIFO + //- Falling edge sync: For the X300, DACCLK is generated using RefClk. Within the + // DAC, the RefClk is sampled by DACCLK to sync interpolation + // stages across multiple DACs. To ensure that we capture the + // RefClk when it is not transitioning, we sample on the falling + // edge of DACCLK + //- Averaging = MAX + write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. + + //Wait for backend SYNC state machine to lock before proceeding. This guarantees that the + //inputs and output of the FIFO have synchronized clocks + _check_dac_sync(); + + //FIFO write pointer offset + //One of ADI's requirements to use data-rate synchronization in PLL mode is to meet + //setup and hold times for RefClk -> DCI clock which we *do not* currently meet in + //the FPGA. The DCI clock reaches a full RefClk cycle later which results in the + //FIFO popping before the first push. This results in a steady-state FIFO fullness + //of pointer - 1. To reach the optimal FIFO fullness of 4 we set the pointer to 5. + //FIXME: At some point we should meet timing on this interface + write_ad9146_reg(0x17, 0x05); + + // We are requesting a soft FIFO align just to put the FIFO + // in a known state. The FRAME will actually do sync the + // FIFO correctly when a stream is created + write_ad9146_reg(0x18, 0x02); // Request soft FIFO align + write_ad9146_reg(0x18, 0x00); // (See above) + + //Verify the FIFO thermometer + _check_frontend_sync(false); //FIFO sanity check } - void check_pll() + // + // Check for PLL lock. Fatal if not locked within timeout + // + void _check_pll() { // Verify PLL is Locked. 1 sec timeout. - // NOTE: Data sheet inconsistant about which pins give PLL lock status. FIXME! + // NOTE: Data sheet inconsistent about which pins give PLL lock status. FIXME! const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(1.0); while (true) { @@ -149,13 +205,16 @@ public: break; if (exit_time < time_spec_t::get_system_time()) throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for DAC PLL to lock"); - if (reg_6 & (1 << 7)) // Sync lost? + if (reg_6 & (1 << 7)) // Lock lost? write_ad9146_reg(0x06, 0xC0); // Clear PLL event flags boost::this_thread::sleep(boost::posix_time::milliseconds(10)); } } - void check_dac_sync() + // + // Check for DAC sync. Fatal if not synced within timeout + // + void _check_dac_sync() { const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(1.0); while (true) @@ -167,19 +226,44 @@ public: break; if (exit_time < time_spec_t::get_system_time()) throw uhd::runtime_error("x300_dac_ctrl: timeout waiting for backend synchronization"); - if (reg_12 & (1 << 7)) // Sync acquired and lost? - arm_dac_sync(); // Re-arm and try again - else if (reg_6 & (1 << 5)) + if (reg_6 & (1 << 5)) write_ad9146_reg(0x06, 0x30); // Clear Sync event flags +#ifdef X300_DAC_RETRY_BACKEND_SYNC + if (reg_12 & (1 << 7)) // Sync acquired and lost? + write_ad9146_reg(0x10, 0xC7); // Enable SYNC mode. Falling edge sync. Averaging set to 128. +#endif } } - void check_frontend_sync() + // + // Check FIFO thermometer. + // + void _check_frontend_sync(bool failure_is_fatal) { // Register 0x19 has a thermometer indicator of the FIFO depth const size_t reg_19 = read_ad9146_reg(0x19); - if ((reg_19 & 0xFF) != 0xF) - UHD_MSG(warning) << "x300_dac_ctrl: unexpected FIFO depth [0x" << std::hex << (reg_19 & 0xFF) << std::dec << "]" << std::endl; + if ((reg_19 & 0xFF) != 0xF) { + std::string msg((boost::format("x300_dac_ctrl: front-end sync failed. unexpected FIFO depth [0x%x]\n") % (reg_19 & 0xFF)).str()); + if (failure_is_fatal) { + throw uhd::runtime_error(msg); + } else { + UHD_MSG(warning) << msg; + } + } + } + + void _sleep_mode(bool sleep) + { + boost::uint8_t sleep_val = sleep ? (1<<7) : 0x00; + //Set sleep word and default fullscale value + write_ad9146_reg(0x41, sleep_val | 0x01); //I DAC + write_ad9146_reg(0x45, sleep_val | 0x01); //Q DAC + } + + void _soft_reset() + { + write_ad9146_reg(0x00, 0x20); // Take DAC into reset. + write_ad9146_reg(0x00, 0x80); // Enable SPI reads and come out of reset } private: diff --git a/host/lib/usrp/x300/x300_dac_ctrl.hpp b/host/lib/usrp/x300/x300_dac_ctrl.hpp index 5fd7e13d8..c2e509b54 100644 --- a/host/lib/usrp/x300/x300_dac_ctrl.hpp +++ b/host/lib/usrp/x300/x300_dac_ctrl.hpp @@ -37,20 +37,14 @@ public: */ static sptr make(uhd::spi_iface::sptr iface, const size_t slaveno, const double clock_rate); - // ! Arm the sync feature in DAC - virtual void arm_dac_sync(void) = 0; - - // ! Check for successful backend sync - virtual void check_dac_sync(void) = 0; - // ! Reset the DAC virtual void reset(void) = 0; - // ! Check for PLL lock - virtual void check_pll(void) = 0; + // ! Reset the DAC and resync + virtual void reset_and_resync(void) = 0; - // ! Check for successful frontend sync - virtual void check_frontend_sync(void) = 0; + // ! Check for successful backend and frontend sync + virtual void verify_sync(void) = 0; }; #endif /* INCLUDED_X300_DAC_CTRL_HPP */ diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index b4286ee79..5520cc82e 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -372,6 +372,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) { const fs_path mb_path = "/mboards/"+boost::lexical_cast(mb_i); mboard_members_t &mb = _mb[mb_i]; + mb.initialization_done = false; mb.addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; mb.xport_path = dev_addr.has_key("resource") ? "nirio" : "eth"; @@ -621,32 +622,18 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) mb.hw_rev = X300_REV("D"); } - //Initialize clock control with internal references and GPSDO power on. - mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; - mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; - mb.clock_control_regs_pps_out_enb = 0; - mb.clock_control_regs_tcxo_enb = 1; - mb.clock_control_regs_gpsdo_pwr = 1; - this->update_clock_control(mb); - - //Create clock control + //Create clock control. NOTE: This does not configure the LMK yet. + initialize_clock_control(mb); mb.clock = x300_clock_ctrl::make(mb.zpu_spi, 1 /*slaveno*/, mb.hw_rev, dev_addr.cast("master_clock_rate", X300_DEFAULT_TICK_RATE), dev_addr.cast("system_ref_rate", X300_DEFAULT_SYSREF_RATE)); - //wait for reference clock to lock - if(mb.hw_rev > 4) - { - try { - //FIXME: Need to verify timeout value to make sure lock can be achieved in < 1.0 seconds - wait_for_ref_locked(mb.zpu_ctrl, 1.0); - } catch (uhd::runtime_error &e) { - //Silently fail for now, but fix after we have the correct timeout value - //UHD_MSG(warning) << "Clock failed to lock to internal source during initialization." << std::endl; - } - } + //Initialize clock source to use internal reference and generate + //a valid radio clock. This may change after configuration is done. + //This will configure the LMK and wait for lock + update_clock_source(mb, "internal"); //////////////////////////////////////////////////////////////////// // create clock properties @@ -750,7 +737,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) _tree->create(mb_path / "clock_source" / "value") .set("internal") .subscribe(boost::bind(&x300_impl::update_clock_source, this, boost::ref(mb), _1)) - .subscribe(boost::bind(&x300_impl::reset_clocks, this, boost::ref(mb))) .subscribe(boost::bind(&x300_impl::reset_radios, this, boost::ref(mb))); static const std::vector clock_source_options = boost::assign::list_of("internal")("external")("gpsdo"); @@ -769,6 +755,22 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) _tree->create(mb_path / "clock_source" / "output") .subscribe(boost::bind(&x300_clock_ctrl::set_ref_out, mb.clock, _1)); + //////////////////////////////////////////////////////////////////// + // initialize clock and time sources + //////////////////////////////////////////////////////////////////// + if (mb.gps and mb.gps->gps_detected()) + { + UHD_MSG(status) << "Initializing clock and time using GPSDO... " << std::flush; + _tree->access(mb_path / "clock_source" / "value").set("gpsdo"); + _tree->access(mb_path / "time_source" / "value").set("gpsdo"); + const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int() + 1); + _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); + } else { + UHD_MSG(status) << "Initializing clock and time using internal sources... " << std::flush; + _tree->access(mb_path / "clock_source" / "value").set("internal"); + _tree->access(mb_path / "time_source" / "value").set("internal"); + } + UHD_MSG(status) << "done" << std::endl; //////////////////////////////////////////////////////////////////// // create frontend mapping @@ -811,25 +813,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) _tree->access(mb_path / "rx_subdev_spec").set(rx_fe_spec); _tree->access(mb_path / "tx_subdev_spec").set(tx_fe_spec); - UHD_MSG(status) << "Initializing clock and PPS references..." << std::endl; - //Set to the GPSDO if installed - if (mb.gps and mb.gps->gps_detected()) - { - _tree->access(mb_path / "clock_source" / "value").set("gpsdo"); - try { - wait_for_ref_locked(mb.zpu_ctrl, 1.0); - } catch (uhd::exception::runtime_error &e) { - UHD_MSG(warning) << "Clock reference failed to lock to GPSDO during device initialization. " << - "Check for the lock before operation or ignore this warning if using another clock source." << std::endl; - } - _tree->access(mb_path / "time_source" / "value").set("gpsdo"); - UHD_MSG(status) << "References initialized to GPSDO sources" << std::endl; - UHD_MSG(status) << "Initializing time to the GPSDO time" << std::endl; - const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1); - _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); - } else { - UHD_MSG(status) << "References initialized to internal sources" << std::endl; - } + mb.initialization_done = true; } x300_impl::~x300_impl(void) @@ -916,14 +900,6 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name) } perif.adc->set_test_word("normal", "normal"); - //////////////////////////////////////////////////////////////// - // Sync DAC's for MIMO - //////////////////////////////////////////////////////////////// - UHD_MSG(status) << "Sync DAC's." << std::endl; - perif.dac->arm_dac_sync(); // Put DAC into data Sync mode - perif.ctrl->poke32(TOREG(SR_DACSYNC), 0x1); // Arm FRAMEP/N sync pulse - - //////////////////////////////////////////////////////////////// // create codec control objects //////////////////////////////////////////////////////////////// @@ -960,8 +936,6 @@ void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name) .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, perif.tx_fe, _1)) .set(std::complex(0.0, 0.0)); - - //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// @@ -1200,10 +1174,10 @@ x300_impl::both_xports_t x300_impl::make_transport( << std::endl; } - size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; + size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size; + size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size; - // Make sure frame sizes do not exceed the max available value supported by UHD + // Make sure frame sizes do not exceed the max available value supported by UHD default_buff_args.send_frame_size = (prefix == X300_RADIO_DEST_PREFIX_TX) ? std::min(system_max_send_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE) @@ -1346,11 +1320,9 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface) UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl; } -void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb) -{ - mb.clock_control_regs_pps_out_enb = enb? 1 : 0; - this->update_clock_control(mb); -} +/*********************************************************************** + * clock and time control logic + **********************************************************************/ void x300_impl::update_clock_control(mboard_members_t &mb) { @@ -1363,79 +1335,71 @@ void x300_impl::update_clock_control(mboard_members_t &mb) mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL), reg); } -void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) +void x300_impl::initialize_clock_control(mboard_members_t &mb) { - mb.clock_control_regs_clock_source = 0; - mb.clock_control_regs_tcxo_enb = 0; - if (source == "internal") { - mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; - mb.clock_control_regs_tcxo_enb = 1; - } else if (source == "external") { - mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; - } else if (source == "gpsdo") { - mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; - } else { - throw uhd::key_error("update_clock_source: unknown source: " + source); - } - + //Initialize clock control register soft copies + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL; + mb.clock_control_regs_pps_out_enb = 0; + mb.clock_control_regs_tcxo_enb = 1; + mb.clock_control_regs_gpsdo_pwr = 1; //GPSDO power always ON this->update_clock_control(mb); - - /* FIXME: implement when we know the correct timeouts - * //wait for lock - * double timeout = 1.0; - * try { - * if (mb.hw_rev > 4) - * wait_for_ref_locked(mb.zpu_ctrl, timeout); - * } catch (uhd::runtime_error &e) { - * //failed to lock on reference - * throw uhd::runtime_error((boost::format("Clock failed to lock to %s source.") % source).str()); - * } - */ } -void x300_impl::reset_clocks(mboard_members_t &mb) +void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb) { - mb.clock->reset_clocks(); - - if (mb.hw_rev > 4) - { - try { - wait_for_ref_locked(mb.zpu_ctrl, 30.0); - } catch (uhd::runtime_error &e) { - //failed to lock on reference - throw uhd::runtime_error((boost::format("PLL failed to lock to reference clock.")).str()); - } - } + mb.clock_control_regs_pps_out_enb = enb? 1 : 0; + this->update_clock_control(mb); } -void x300_impl::reset_radios(mboard_members_t &mb) +void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source) { - // reset ADCs and DACs - BOOST_FOREACH (radio_perifs_t& perif, mb.radio_perifs) - { - perif.adc->reset(); - perif.dac->reset(); - } + //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 + //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 + mb.clock_control_regs_clock_source = 0; + mb.clock_control_regs_tcxo_enb = 0; + if (source == "internal") { + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL; + mb.clock_control_regs_tcxo_enb = 1; + } else if (source == "external") { + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL; + } else if (source == "gpsdo") { + mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO; + } else { + throw uhd::key_error("update_clock_source: unknown source: " + source); + } + this->update_clock_control(mb); - // check PLL locks - BOOST_FOREACH (radio_perifs_t& perif, mb.radio_perifs) - { - perif.dac->check_pll(); + //Reset the LMK to make sure it re-locks to the new reference + mb.clock->reset_clocks(); } - // Sync DACs - BOOST_FOREACH (radio_perifs_t& perif, mb.radio_perifs) - { - perif.dac->arm_dac_sync(); - } - BOOST_FOREACH (radio_perifs_t& perif, mb.radio_perifs) - { - perif.dac->check_dac_sync(); - // Arm FRAMEP/N sync pulse - // TODO: Investigate timing of the sync frame pulse. - perif.ctrl->poke32(TOREG(SR_DACSYNC), 0x1); - perif.dac->check_frontend_sync(); + //Wait for the LMK to lock (always, as a sanity check that the clock is useable) + //* Currently the LMK can take as long as 30 seconds to lock to a reference but we don't + //* want to wait that long during initialization. + //TODO: Need to verify timeout and settings to make sure lock can be achieved in < 1.0 seconds + double timeout = mb.initialization_done ? 30.0 : 1.0; + + //The programming code in x300_clock_ctrl is not compatible with revs <= 4 and may + //lead to locking issues. So, disable the ref-locked check for older (unsupported) boards. + if (mb.hw_rev > 4) { + if (not wait_for_ref_locked(mb.zpu_ctrl, timeout)) { + //failed to lock on reference + if (mb.initialization_done) { + throw uhd::runtime_error((boost::format("Reference Clock failed to lock to %s source.") % source).str()); + } else { + //TODO: Re-enable this warning when we figure out a reliable lock time + //UHD_MSG(warning) << "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." << std::endl; + } + } } + + //Update cache value + mb.current_refclk_src = source; } void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source) @@ -1460,18 +1424,18 @@ void x300_impl::update_time_source(mboard_members_t &mb, const std::string &sour } } -void x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout) +bool x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout) { boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0); do { if (get_ref_locked(ctrl).to_bool()) - return; + return true; boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } while (boost::get_system_time() < timeout_time); //failed to lock on reference - throw uhd::runtime_error("The reference clock failed to lock."); + return false; } sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) @@ -1496,6 +1460,67 @@ bool x300_impl::is_pps_present(wb_iface::sptr ctrl) return false; } +/*********************************************************************** + * reset and synchronization logic + **********************************************************************/ + +void x300_impl::reset_radios(mboard_members_t &mb) +{ + // Reset ADCs and DACs + BOOST_FOREACH (radio_perifs_t& perif, mb.radio_perifs) + { + perif.adc->reset(); + perif.dac->reset(); + } +} + +void x300_impl::synchronize_dacs(const std::vector& radios) +{ + if (radios.size() < 2) return; //Nothing to synchronize + + //**PRECONDITION** + //This function assumes that all the VITA times in "radios" are synchronized + //to a common reference. Currently, this function is called in get_tx_stream + //which also has the same precondition. + + //Reinitialize and resync all DACs + for (size_t i = 0; i < radios.size(); i++) { + radios[i]->dac->reset_and_resync(); + } + + //Get a rough estimate of the cumulative command latency + boost::posix_time::ptime t_start = boost::posix_time::microsec_clock::local_time(); + for (size_t i = 0; i < radios.size(); i++) { + radios[i]->ctrl->peek64(RB64_TIME_NOW); //Discard value. We are just timing the call + } + boost::posix_time::time_duration t_elapsed = + boost::posix_time::microsec_clock::local_time() - t_start; + + //Add 100% of headroom + uncertaintly to the command time + boost::uint64_t t_sync_us = (t_elapsed.total_microseconds() * 2) + 13000 /*Scheduler latency*/; + + //Pick radios[0] as the time reference. + uhd::time_spec_t sync_time = + radios[0]->time64->get_time_now() + uhd::time_spec_t(((double)t_sync_us)/1e6); + + //Send the sync command + for (size_t i = 0; i < radios.size(); i++) { + radios[i]->ctrl->set_time(sync_time); + radios[i]->ctrl->poke32(TOREG(SR_DACSYNC), 0x1); //Arm FRAMEP/N sync pulse + radios[i]->ctrl->set_time(uhd::time_spec_t(0.0)); //Clear command time + } + + //Wait and check status + boost::this_thread::sleep(boost::posix_time::microseconds(t_sync_us)); + for (size_t i = 0; i < radios.size(); i++) { + radios[i]->dac->verify_sync(); + } +} + +/*********************************************************************** + * eeprom + **********************************************************************/ + void x300_impl::set_db_eeprom(i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t &db_eeprom) { db_eeprom.store(*i2c, addr); @@ -1507,6 +1532,10 @@ void x300_impl::set_mb_eeprom(i2c_iface::sptr i2c, const mboard_eeprom_t &mb_eep mb_eeprom.commit(*eeprom16, "X300"); } +/*********************************************************************** + * front-panel GPIO + **********************************************************************/ + boost::uint32_t x300_impl::get_fp_gpio(gpio_core_200::sptr gpio, const std::string &) { return boost::uint32_t(gpio->read_gpio(dboard_iface::UNIT_RX)); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 924cb61a4..70c5dccb4 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -194,6 +194,7 @@ private: uhd::dict > rx_streamers; uhd::dict > tx_streamers; + bool initialization_done; uhd::task::sptr claimer_task; std::string addr; std::string xport_path; @@ -233,6 +234,7 @@ private: std::string loaded_fpga_image; size_t hw_rev; + std::string current_refclk_src; }; std::vector _mb; @@ -341,14 +343,14 @@ private: void update_tx_samp_rate(mboard_members_t&, const size_t, const double); void update_clock_control(mboard_members_t&); + void initialize_clock_control(mboard_members_t &mb); void set_time_source_out(mboard_members_t&, const bool); void update_clock_source(mboard_members_t&, const std::string &); void update_time_source(mboard_members_t&, const std::string &); - void reset_clocks(mboard_members_t&); void reset_radios(mboard_members_t&); uhd::sensor_value_t get_ref_locked(uhd::wb_iface::sptr); - void wait_for_ref_locked(uhd::wb_iface::sptr, double timeout = 0.0); + bool wait_for_ref_locked(uhd::wb_iface::sptr, double timeout = 0.0); bool is_pps_present(uhd::wb_iface::sptr); void set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &); @@ -360,6 +362,12 @@ private: 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); + + //**PRECONDITION** + //This function assumes that all the VITA times in "radios" are synchronized + //to a common reference. Currently, this function is called in get_tx_stream + //which also has the same precondition. + static void synchronize_dacs(const std::vector& mboards); }; #endif /* INCLUDED_X300_IMPL_HPP */ diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index c5b8f49e3..04042049d 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -540,6 +540,7 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) //shared async queue for all channels in streamer boost::shared_ptr async_md(new async_md_type(1000/*messages deep*/)); + std::vector radios_list; boost::shared_ptr my_streamer; for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) { @@ -557,9 +558,10 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) } // Find the DSP that corresponds to this mainboard and subdev mboard_members_t &mb = _mb[mb_index]; - const size_t radio_index = _tree->access >("/mboards/" + boost::lexical_cast(mb_index) / "tx_chan_dsp_mapping") + const size_t radio_index = _tree->access >("/mboards/" + boost::lexical_cast(mb_index) / "tx_chan_dsp_mapping") .get().at(mb_chan); radio_perifs_t &perif = mb.radio_perifs[radio_index]; + radios_list.push_back(&perif); //setup the dsp transport hints (TODO) device_addr_t device_addr = mb.send_args; @@ -571,8 +573,8 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_TX, device_addr, data_sid); UHD_LOG << boost::format("data_sid = 0x%08x\n") % data_sid << std::endl; - // To calculate the max number of samples per packet, we assume the maximum header length - // to avoid fragmentation should the entire header be used. + // To calculate the max number of samples per packet, we assume the maximum header length + // to avoid fragmentation should the entire header be used. const size_t bpp = xport.send->get_send_frame_size() - X300_TX_MAX_HDR_LEN; const size_t bpi = convert::get_bytes_per_item(args.otw_format); const size_t spp = unsigned(args.args.cast("spp", bpp/bpi)); @@ -640,5 +642,6 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) _tree->access(mb_path / "tx_dsps" / boost::lexical_cast(radio_index) / "rate" / "value").update(); } + synchronize_dacs(radios_list); return my_streamer; } -- cgit v1.2.3 From 6714ac0af376ab98f42f49e3f9fa2ceef359c109 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 17 Apr 2014 10:05:57 +0200 Subject: b200: Make the master clock rate auto-configurable When no master_clock_rate is defined, the B200 driver will now select a suitable clock rate automatically based on the selected sampling rate. The selected tick rate is a multiple of the LCM of tx and rx rates. Auto-setting is done every time a streamer is generated or the sampling rate is configured. --- host/lib/usrp/b200/b200_impl.cpp | 32 +++++--- host/lib/usrp/b200/b200_impl.hpp | 58 ++++++++++++-- host/lib/usrp/b200/b200_io_impl.cpp | 156 +++++++++++++++++++++++++++++++----- 3 files changed, 210 insertions(+), 36 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index da06e12b4..6d1172c98 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -416,6 +416,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr) .publish(boost::bind(&b200_impl::get_tick_rate, this)) .subscribe(boost::bind(&b200_impl::update_tick_rate, this, _1)); _tree->create(mb_path / "time" / "cmd"); + _tree->create(mb_path / "auto_tick_rate").set(false); //////////////////////////////////////////////////////////////////// // and do the misc mboard sensors @@ -516,6 +517,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr) _tree->access(mb_path / "rx_dsps" / str(boost::format("%u") % i)/ "rate/value").set(B200_DEFAULT_RATE); _tree->access(mb_path / "tx_dsps" / str(boost::format("%u") % i) / "rate/value").set(B200_DEFAULT_RATE); } + // We can automatically choose a master clock rate, but not if the user specifies one + _tree->access(mb_path / "auto_tick_rate").set(not device_addr.has_key("master_clock_rate")); + if (not device_addr.has_key("master_clock_rate")) { + UHD_MSG(status) << "Setting master clock rate selection to 'automatic'." << std::endl; + } //GPS installed: use external ref, time, and init time spec if (_gps and _gps->gps_detected()) @@ -579,7 +585,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create(rx_dsp_path / "rate" / "range") .publish(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc)); _tree->create(rx_dsp_path / "rate" / "value") - .coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1)) + .coerce(boost::bind(&b200_impl::coerce_rx_samp_rate, this, perif.ddc, dspno, _1)) .subscribe(boost::bind(&b200_impl::update_rx_samp_rate, this, dspno, _1)) .set(0.0); // Can only set this after tick rate is initialized. _tree->create(rx_dsp_path / "freq" / "value") @@ -603,7 +609,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create(tx_dsp_path / "rate" / "range") .publish(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc)); _tree->create(tx_dsp_path / "rate" / "value") - .coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1)) + .coerce(boost::bind(&b200_impl::coerce_tx_samp_rate, this, perif.duc, dspno, _1)) .subscribe(boost::bind(&b200_impl::update_tx_samp_rate, this, dspno, _1)) .set(0.0); // Can only set this after tick rate is initialized. _tree->create(tx_dsp_path / "freq" / "value") @@ -719,7 +725,7 @@ void b200_impl::codec_loopback_self_test(wb_iface::sptr iface) /*********************************************************************** * Sample and tick rate comprehension below **********************************************************************/ -void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction /*= ""*/) { const size_t max_chans = 2; if (chan_count > max_chans) @@ -727,7 +733,7 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co throw uhd::value_error(boost::str( boost::format("cannot not setup %d %s channels (maximum is %d)") % chan_count - % (direction ? direction : "data") + % (direction.empty() ? "data" : direction) % max_chans )); } @@ -741,20 +747,26 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co % (tick_rate/1e6) % (max_tick_rate/1e6) % chan_count - % (direction ? direction : "data") + % (direction.empty() ? "data" : direction) )); } } } -double b200_impl::set_tick_rate(const double rate) +double b200_impl::set_tick_rate(const double new_tick_rate) { - UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz\n") % (rate/1e6)); + UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz... ") % (new_tick_rate/1e6)) << std::flush; + check_tick_rate_with_current_streamers(new_tick_rate); // Defined in b200_io_impl.cpp - check_tick_rate_with_current_streamers(rate); // Defined in b200_io_impl.cpp + // Make sure the clock rate is actually changed before doing + // the full Monty of setting regs and loopback tests etc. + if (std::abs(new_tick_rate - _tick_rate) < 1.0) { + UHD_MSG(status) << "OK" << std::endl; + return _tick_rate; + } - _tick_rate = _codec_ctrl->set_clock_rate(rate); - UHD_MSG(status) << (boost::format("Actually got clock rate %.6f MHz\n") % (_tick_rate/1e6)); + _tick_rate = _codec_ctrl->set_clock_rate(new_tick_rate); + UHD_MSG(status) << std::endl << (boost::format("Actually got clock rate %.6f MHz.") % (_tick_rate/1e6)) << std::endl; //reset after clock rate change this->reset_codec_dcm(); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 613844ffc..8e23ea6a0 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -98,7 +98,13 @@ public: uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); - void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL); + + //! Check that the combination of stream args and tick rate are valid. + // + // Basically figures out the arguments for enforce_tick_rate_limits() + // and calls said method. If arguments are invalid, throws a + // uhd::value_error. + void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = ""); private: //controllers @@ -114,9 +120,6 @@ private: uhd::transport::zero_copy_if::sptr _ctrl_transport; uhd::usrp::recv_packet_demuxer_3000::sptr _demux; - boost::weak_ptr _rx_streamer; - boost::weak_ptr _tx_streamer; - //async ctrl + msgs uhd::msg_task::sptr _async_task; typedef uhd::transport::bounded_buffer async_md_type; @@ -188,11 +191,56 @@ private: double _tick_rate; double get_tick_rate(void){return _tick_rate;} double set_tick_rate(const double rate); + + /*! \brief Choose a tick rate (master clock rate) that works well for the given sampling rate. + * + * This function will try and choose a master clock rate automatically. + * See the function definition for details on the algorithm. + * + * The chosen tick rate is the largest multiple of two that is smaler + * than the max tick rate. + * The base rate is either given explicitly, or is the lcm() of the tx + * and rx sampling rates. In that case, it reads the rates directly + * from the property tree. It also tries to guess the number of channels + * (for the max possible tick rate) by checking the available streamers. + * This value, too, can explicitly be given. + * + * \param rate If this is given, it will be used as a minimum rate, or + * argument to lcm(). + * \param tree_dsp_path The sampling rate from this property tree path + * will be ignored. + * \param num_chans If given, specifies the number of channels. + */ + void set_auto_tick_rate( + const double rate=0, + const uhd::fs_path &tree_dsp_path="", + size_t num_chans=0 + ); + void update_tick_rate(const double); - void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction = NULL); + + /*! Check if \p tick_rate works with \p chan_count channels. + * + * Throws a uhd::value_error if not. + */ + void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction = ""); void check_tick_rate_with_current_streamers(double rate); + /*! Return the max number of channels on active rx_streamer or tx_streamer objects associated with this device. + * + * \param direction Set to "TX" to only check tx_streamers, "RX" to only check + * rx_streamers. Any other value will check if \e any active + * streamers are available. + * \return Return the number of tx streamers (direction=="TX"), the number of rx + * streamers (direction=="RX") or the total number of streamers. + */ + size_t max_chan_count(const std::string &direction=""); + + //! 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_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp index 9f6d593fe..cb32c610a 100644 --- a/host/lib/usrp/b200/b200_io_impl.cpp +++ b/host/lib/usrp/b200/b200_io_impl.cpp @@ -1,5 +1,5 @@ // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-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 @@ -21,8 +21,10 @@ #include "../../transport/super_recv_packet_handler.hpp" #include "../../transport/super_send_packet_handler.hpp" #include "async_packet_handler.hpp" +#include #include #include +#include #include using namespace uhd; @@ -34,30 +36,32 @@ using namespace uhd::transport; **********************************************************************/ void b200_impl::check_tick_rate_with_current_streamers(double rate) { - size_t max_tx_chan_count = 0, max_rx_chan_count = 0; + // Defined in b200_impl.cpp + enforce_tick_rate_limits(max_chan_count("RX"), rate, "RX"); + enforce_tick_rate_limits(max_chan_count("TX"), rate, "TX"); +} + +// direction can either be "TX", "RX", or empty (default) +size_t b200_impl::max_chan_count(const std::string &direction /* = "" */) +{ + size_t max_count = 0; BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { - { + if ((direction == "RX" or direction.empty()) and not perif.rx_streamer.expired()) { boost::shared_ptr rx_streamer = boost::dynamic_pointer_cast(perif.rx_streamer.lock()); - if (rx_streamer) - max_rx_chan_count = std::max(max_rx_chan_count, rx_streamer->get_num_channels()); + max_count = std::max(max_count, rx_streamer->get_num_channels()); } - - { + if ((direction == "TX" or direction.empty()) and not perif.tx_streamer.expired()) { boost::shared_ptr tx_streamer = boost::dynamic_pointer_cast(perif.tx_streamer.lock()); - if (tx_streamer) - max_tx_chan_count = std::max(max_tx_chan_count, tx_streamer->get_num_channels()); + max_count = std::max(max_count, tx_streamer->get_num_channels()); } } - - // Defined in b200_impl.cpp - enforce_tick_rate_limits(max_rx_chan_count, rate, "RX"); - enforce_tick_rate_limits(max_tx_chan_count, rate, "TX"); + return max_count; } -void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction /*= NULL*/) +void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction /*= ""*/) { std::set chans_set; for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) @@ -69,26 +73,120 @@ void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_ enforce_tick_rate_limits(chans_set.size(), tick_rate, direction); // Defined in b200_impl.cpp } -void b200_impl::update_tick_rate(const double rate) +void b200_impl::set_auto_tick_rate( + const double rate, + const fs_path &tree_dsp_path, + size_t num_chans +) { + if (num_chans == 0) { // Divine them + num_chans = std::max(size_t(1), max_chan_count()); + } + + // See also the doxygen documentation for these steps in b200_impl.hpp + // Step 1: Obtain LCM and max rate from all relevant dsps + boost::uint32_t lcm_rate = (rate == 0) ? 1 : static_cast(floor(rate + 0.5)); + for (int i = 0; i < 2; i++) { // Loop through rx and tx + std::string dir = (i == 0) ? "tx" : "rx"; + // We have no way of knowing which DSPs are used, so we check them all. + BOOST_FOREACH(const std::string &dsp_no, _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) { + fs_path dsp_path = str(boost::format("/mboards/0/%s_dsps/%s") % dir % dsp_no); + if (dsp_path == tree_dsp_path) { + continue; + } + double this_dsp_rate = _tree->access(dsp_path / "rate/value").get(); + // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set + // the sampling rate. If the user *did* set the rate to + // B200_DEFAULT_RATE on all DSPs, then this will still work (see below). + // If the user set one DSP to B200_DEFAULT_RATE and the other to + // a different rate, this also works if the rates are integer multiples + // of one another. Only for certain configurations of B200_DEFAULT_RATE + // and another rate that is not an integer multiple, this will be problematic. + // Since this case is less common than the case where a rate is left unset, + // we don't handle that but rather explain that corner case in the documentation. + if (this_dsp_rate == B200_DEFAULT_RATE) { + continue; + } + lcm_rate = boost::math::lcm( + lcm_rate, + static_cast(floor(this_dsp_rate + 0.5)) + ); + } + } + if (lcm_rate == 1) { + lcm_rate = static_cast(B200_DEFAULT_RATE); + } + + // Step 2: Determine whether if we can use lcm_rate (preferred), + // or have to give up because too large: + const double max_tick_rate = + ((num_chans <= 1) ? ad9361_device_t::AD9361_RECOMMENDED_MAX_CLOCK_RATE : ad9361_device_t::AD9361_MAX_CLOCK_RATE/2); + double base_rate = static_cast(lcm_rate); + if (base_rate > max_tick_rate) { + UHD_MSG(warning) + << "Cannot automatically determine an appropriate tick rate for these sampling rates." << std::endl + << "Consider using different sampling rates, or manually specify a suitable master clock rate." << std::endl; + return; // Let the others handle this + } + + // Step 3: Choose the new rate + // Rules for choosing the tick rate: + // Choose a rate that is a power of 2 larger than the sampling rate, + // but at least 4. Cannot exceed the max tick rate, of course, but must + // be larger than the minimum tick rate. + // An equation that does all that is: + // + // f_auto = r * 2^floor(log2(f_max/r)) + // + // where r is the base rate and f_max is the maximum tick rate. The case + // where floor() yields 1 must be caught. + const double min_tick_rate = _codec_ctrl->get_clock_rate_range().start(); + // We use shifts here instead of 2^x because exp2() is not available in all compilers, + // also this guarantees no rounding issues. The type cast to int32_t serves as floor(): + boost::int32_t multiplier = (1 << boost::int32_t(uhd::math::log2(max_tick_rate / base_rate))); + if (multiplier == 2 and base_rate >= min_tick_rate) { + // Don't bother (see above) + multiplier = 1; + } + double new_rate = base_rate * multiplier; + UHD_ASSERT_THROW(new_rate >= min_tick_rate); + UHD_ASSERT_THROW(new_rate <= max_tick_rate); + + if (_tree->access("/mboards/0/tick_rate").get() != new_rate) { + _tree->access("/mboards/0/tick_rate").set(new_rate); + } +} + +void b200_impl::update_tick_rate(const double new_tick_rate) { - check_tick_rate_with_current_streamers(rate); + check_tick_rate_with_current_streamers(new_tick_rate); BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(perif.rx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(rate); - perif.framer->set_tick_rate(_tick_rate); + if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + perif.framer->set_tick_rate(new_tick_rate); } BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs) { boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(perif.tx_streamer.lock()); - if (my_streamer) my_streamer->set_tick_rate(rate); - perif.deframer->set_tick_rate(_tick_rate); + if (my_streamer) my_streamer->set_tick_rate(new_tick_rate); + perif.deframer->set_tick_rate(new_tick_rate); } } + +double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate) +{ + // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate + if (_tree->access("/mboards/0/auto_tick_rate").get()) { + const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str(); + set_auto_tick_rate(rx_rate, dsp_path); + } + return ddc->set_host_rate(rx_rate); +} + void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr my_streamer = @@ -99,6 +197,16 @@ void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate) my_streamer->set_scale_factor(adj); } +double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate) +{ + // Have to set tick rate first, or the duc will change the requested rate based on default tick rate + if (_tree->access("/mboards/0/auto_tick_rate").get()) { + const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str(); + set_auto_tick_rate(tx_rate, dsp_path); + } + return duc->set_host_rate(tx_rate); +} + void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate) { boost::shared_ptr my_streamer = @@ -262,6 +370,9 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_) if (args.otw_format.empty()) args.otw_format = "sc16"; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + if (_tree->access("/mboards/0/auto_tick_rate").get()) { + set_auto_tick_rate(0, "", args.channels.size()); + } check_streamer_args(args, this->get_tick_rate(), "RX"); boost::shared_ptr my_streamer; @@ -367,7 +478,10 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_) if (args.otw_format.empty()) args.otw_format = "sc16"; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; - check_streamer_args(args, this->get_tick_rate(), "TX"); + if (_tree->access("/mboards/0/auto_tick_rate").get()) { + set_auto_tick_rate(0, "", args.channels.size()); + } + check_streamer_args(args, this->get_tick_rate(), "RX"); boost::shared_ptr my_streamer; for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++) -- cgit v1.2.3 From beabf3d302a98a0a1e28ae8cc4d338f0bd13db6e Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Mon, 3 Nov 2014 17:05:26 -0800 Subject: uhd: replaced the `images_error` with a generic utility error - Deleted images.*, moved functionality to paths.* - Applies for all devices that check FPGA or FW compat numbers - Adds generic utility search tool --- host/include/uhd/utils/CMakeLists.txt | 1 - host/include/uhd/utils/images.hpp | 53 ----------------------- host/include/uhd/utils/paths.hpp | 25 +++++++++++ host/lib/usrp/b100/b100_impl.cpp | 10 ++--- host/lib/usrp/b100/b100_impl.hpp | 2 +- host/lib/usrp/b200/b200_impl.cpp | 15 +++---- host/lib/usrp/b200/b200_impl.hpp | 6 +-- host/lib/usrp/e100/e100_impl.cpp | 4 +- host/lib/usrp/e300/e300_impl.cpp | 4 +- host/lib/usrp/e300/e300_network.cpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_iface.cpp | 8 ++-- host/lib/usrp/x300/x300_impl.cpp | 14 +++--- host/lib/usrp_clock/octoclock/octoclock_impl.cpp | 6 +-- host/lib/utils/CMakeLists.txt | 1 - host/lib/utils/images.cpp | 54 ------------------------ host/lib/utils/paths.cpp | 37 ++++++++++++++-- host/utils/b2xx_fx3_utils.cpp | 2 +- host/utils/octoclock_firmware_burner.cpp | 2 +- host/utils/usrp_n2xx_simple_net_burner.cpp | 2 +- host/utils/usrp_x3xx_fpga_burner.cpp | 2 +- 21 files changed, 99 insertions(+), 155 deletions(-) delete mode 100644 host/include/uhd/utils/images.hpp delete mode 100644 host/lib/utils/images.cpp (limited to 'host/lib') diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index c308c9cde..05f6892d2 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -25,7 +25,6 @@ UHD_INSTALL(FILES cast.hpp csv.hpp gain_group.hpp - images.hpp log.hpp math.hpp msg.hpp diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp deleted file mode 100644 index a0934fb08..000000000 --- a/host/include/uhd/utils/images.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright 2010,2012 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 . -// - -#ifndef INCLUDED_UHD_UTILS_IMAGES_HPP -#define INCLUDED_UHD_UTILS_IMAGES_HPP - -#include -#include - -namespace uhd{ - - /*! - * Search for an image in the system image paths: - * Search compiled-in paths and environment variable paths - * for a specific image file with the provided file name. - * \param image_name the name of the file - * \return the full system path to the file - * \throw exception if the image was not found - */ - UHD_API std::string find_image_path(const std::string &image_name); - - /*! - * Search for the location of the UHD Images Downloader script. - * \return the full system path to uhd_images_downloader.py - */ - - UHD_API std::string find_images_downloader(void); - - /*! - * Return the error string for recommending using the UHD Images Downloader. - * String depends on OS. - * \return the message suggesting the use of uhd_images_downloader.py - */ - - UHD_API std::string print_images_error(void); - -} //namespace uhd - -#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/paths.hpp b/host/include/uhd/utils/paths.hpp index e0f455e92..c1f32ba61 100644 --- a/host/include/uhd/utils/paths.hpp +++ b/host/include/uhd/utils/paths.hpp @@ -32,6 +32,31 @@ namespace uhd{ //! Get a string representing the system's pkg directory UHD_API std::string get_pkg_path(void); + /*! + * Search for an image in the system image paths: + * Search compiled-in paths and environment variable paths + * for a specific image file with the provided file name. + * \param image_name the name of the file + * \return the full system path to the file + * \throw exception if the image was not found + */ + UHD_API std::string find_image_path(const std::string &image_name); + + /*! + * Search for the location of a particular UHD utility. + * The utility must be installed in the `uhd/utils` directory. + * \param the name of the utility to search for + * \return the full system path to @param + */ + UHD_API std::string find_utility(std::string name); + + /*! + * Return an error string recommending the user run the utility. + * The error string will include the full path to the utility to run. + * \return the message suggesting the use of the named utility. + */ + UHD_API std::string print_utility_error(std::string name); + } //namespace uhd #endif /* INCLUDED_UHD_UTILS_PATHS_HPP */ diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 24a87a3c8..c4279913c 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -82,7 +82,7 @@ static device_addrs_t b100_find(const device_addr_t &hint) b100_fw_image = find_image_path(hint.get("fw", B100_FW_FILE_NAME)); } catch(...){ - UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_images_error(); + UHD_MSG(warning) << boost::format("Could not locate B100 firmware. %s\n") % print_utility_error("uhd_images_downloader.py"); return b100_addrs; } UHD_LOG << "the firmware image: " << b100_fw_image << std::endl; @@ -532,10 +532,10 @@ void b100_impl::check_fw_compat(void){ ); if (fw_compat_num != B100_FW_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x:\n" + "Expected firmware compatibility number %d, but got %d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % B100_FW_COMPAT_NUM % fw_compat_num % print_images_error())); + ) % int(B100_FW_COMPAT_NUM) % fw_compat_num % print_utility_error("uhd_images_downloader.py"))); } _tree->create("/mboards/0/fw_version").set(str(boost::format("%u.0") % fw_compat_num)); } @@ -552,7 +552,7 @@ void b100_impl::check_fpga_compat(void){ "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build." "%s" - ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_images_error())); + ) % int(B100_FPGA_COMPAT_NUM) % fpga_major % print_utility_error("uhd_images_downloader.py"))); } _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); } diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 59ea2202e..dbca543be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -46,7 +46,7 @@ static const double B100_LINK_RATE_BPS = 256e6/5; //pratical link rate (< 480 Mbps) static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; -static const boost::uint16_t B100_FW_COMPAT_NUM = 0x04; +static const boost::uint16_t B100_FW_COMPAT_NUM = 4; static const boost::uint16_t B100_FPGA_COMPAT_NUM = 11; static const boost::uint32_t B100_RX_SID_BASE = 30; static const boost::uint32_t B100_TX_ASYNC_SID = 10; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 6d1172c98..b3c190c50 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -115,7 +115,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) UHD_MSG(warning) << boost::format( "Could not locate B200 firmware.\n" "Please install the images package. %s\n" - ) % print_images_error(); + ) % print_utility_error("uhd_images_downloader.py"); return b200_addrs; } UHD_LOG << "the firmware image: " << b200_fw_image << std::endl; @@ -791,11 +791,11 @@ void b200_impl::check_fw_compat(void) if (compat_major != B200_FW_COMPAT_NUM_MAJOR){ throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected firmware compatibility number %d.%d, but got %d.%d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % int(B200_FW_COMPAT_NUM_MAJOR) % compat_major % compat_minor - % print_images_error())); + ) % int(B200_FW_COMPAT_NUM_MAJOR) % int(B200_FW_COMPAT_NUM_MINOR) + % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py"))); } _tree->create("/mboards/0/fw_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); @@ -812,11 +812,10 @@ void b200_impl::check_fpga_compat(void) if (compat_major != B200_FPGA_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build.\n" "%s" - ) % int(B200_FPGA_COMPAT_NUM) % compat_major % compat_minor - % print_images_error())); + ) % int(B200_FPGA_COMPAT_NUM) % compat_major % print_utility_error("uhd_images_downloader.py"))); } _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp index 22e962bd5..71592f60b 100644 --- a/host/lib/usrp/b200/b200_impl.hpp +++ b/host/lib/usrp/b200/b200_impl.hpp @@ -45,9 +45,9 @@ #include #include #include "recv_packet_demuxer_3000.hpp" -static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x07; -static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00; -static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x04; +static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 7; +static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0; +static const boost::uint16_t B200_FPGA_COMPAT_NUM = 4; static const double B200_BUS_CLOCK_RATE = 100e6; static const double B200_DEFAULT_TICK_RATE = 32e6; static const double B200_DEFAULT_FREQ = 100e6; // Hz diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8b4f2316c..ac419e0e0 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -132,7 +132,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ e100_fpga_image = find_image_path(device_addr.get("fpga", default_fpga_file_name)); } catch(...){ - UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_images_error(); + UHD_MSG(error) << boost::format("Could not find FPGA image. %s\n") % print_utility_error("uhd_images_downloader.py"); throw; } e100_load_fpga(e100_fpga_image); diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index e42ac390e..8807a56e4 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -397,7 +397,7 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr) "%s" ) % fpga::COMPAT_MAJOR % _get_version(FPGA_MAJOR) % _get_version(FPGA_MINOR) - % print_images_error())); + % print_utility_error("uhd_images_downloader.py"))); } //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 883ff0c4f..59e1eec86 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 709092e42..dbd5408e8 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -85,7 +85,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) usrp1_fw_image = find_image_path(hint.get("fw", "usrp1_fw.ihx")); } catch(...){ - UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_images_error(); + UHD_MSG(warning) << boost::format("Could not locate USRP1 firmware. %s") % print_utility_error("uhd_images_downloader.py"); } UHD_LOG << "USRP1 firmware image: " << usrp1_fw_image << std::endl; diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index b2085807f..65cf90a17 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -375,7 +375,7 @@ public: fpga_image_path = uhd::find_image_path(fpga_image); } catch(const std::exception &){ - return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_images_error()); + return str(boost::format("Could not find %s and %s in your images path!\n%s") % fw_image % fpga_image % print_utility_error("uhd_images_downloader.py")); } //escape char for multi-line cmd + newline + indent? @@ -389,13 +389,13 @@ public: if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){ const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner.py").string(); const std::string card_burner_cmd = str(boost::format("\"%s%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); - return str(boost::format("%s\n%s") % print_images_error() % card_burner_cmd); + return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd); } else{ const std::string addr = _ctrl_transport->get_recv_addr(); const std::string net_burner_path = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp_n2xx_simple_net_burner").string(); const std::string net_burner_cmd = str(boost::format("\"%s\" %s--addr=\"%s\"") % net_burner_path % ml % addr); - return str(boost::format("%s\n%s") % print_images_error() % net_burner_cmd); + return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % net_burner_cmd); } } diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index a879ae02d..8d255097d 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -24,7 +24,7 @@ #include "apply_corrections.hpp" #include #include -#include +#include #include #include #include @@ -171,7 +171,7 @@ static device_addrs_t x300_find_pcie(const device_addr_t &hint, bool explicit_qu default: continue; } - + niriok_proxy::sptr kernel_proxy = niriok_proxy::make_and_open(dev_info.interface_path); //Attempt to read the name from the EEPROM and perform filtering. @@ -1670,11 +1670,11 @@ void x300_impl::check_fw_compat(const fs_path &mb_path, wb_iface::sptr iface) if (compat_major != X300_FW_COMPAT_MAJOR) { throw uhd::runtime_error(str(boost::format( - "Expected firmware compatibility number 0x%x, but got 0x%x.%x:\n" + "Expected firmware compatibility number %d.%d, but got %d.%d:\n" "The firmware build is not compatible with the host code build.\n" "%s" - ) % int(X300_FW_COMPAT_MAJOR) % compat_major % compat_minor - % print_images_error())); + ) % int(X300_FW_COMPAT_MAJOR) % int(X300_FW_COMPAT_MINOR) + % compat_major % compat_minor % print_utility_error("uhd_images_downloader.py"))); } _tree->create(mb_path / "fw_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); @@ -1694,11 +1694,11 @@ void x300_impl::check_fpga_compat(const fs_path &mb_path, wb_iface::sptr iface) "Download the appropriate FPGA images for this version of UHD.\n" "%s\n\n" "Then burn a new image to the on-board flash storage of your\n" - "USRP X3xx device using the burner utility. \n\n" + "USRP X3xx device using the burner utility. %s\n\n" "For more information, refer to the UHD manual:\n\n" " http://files.ettus.com/manual/page_usrp_x3x0.html#x3x0_flash" ) % int(X300_FPGA_COMPAT_MAJOR) % compat_major - % print_images_error())); + % print_utility_error("uhd_images_downloader.py") % print_utility_error("usrp_x3xx_fpga_burner"))); } _tree->create(mb_path / "fpga_version").set(str(boost::format("%u.%u") % compat_major % compat_minor)); diff --git a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp index 8c207dd9f..d55fab10e 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -420,7 +420,7 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){ catch(const std::exception &e){ return str(boost::format("Could not find %s in your images path.\n%s") % image_name - % uhd::print_images_error()); + % uhd::print_utility_error("uhd_images_downloader.py")); } //Get escape character @@ -433,5 +433,5 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){ //Get burner command const std::string burner_path = (fs::path(uhd::get_pkg_path()) / "bin" / "octoclock_firmware_burner").string(); const std::string burner_cmd = str(boost::format("%s %s--addr=\"%s\"") % burner_path % ml % addr); - return str(boost::format("%s\n%s") % uhd::print_images_error() % burner_cmd); + return str(boost::format("%s\n%s") % uhd::print_utility_error("uhd_images_downloader.py") % burner_cmd); } diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 106e2b650..369920ac1 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -132,7 +132,6 @@ SET_SOURCE_FILES_PROPERTIES( LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/images.cpp ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp deleted file mode 100644 index 1ba2f81e6..000000000 --- a/host/lib/utils/images.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010-2012 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 . -// - -#include -#include -#include -#include -#include -#include -#include - -namespace fs = boost::filesystem; - -std::vector get_image_paths(void); //defined in paths.cpp - -/*********************************************************************** - * Find an image in the image paths - **********************************************************************/ -std::string uhd::find_image_path(const std::string &image_name){ - if (fs::exists(image_name)){ - return fs::system_complete(image_name).string(); - } - BOOST_FOREACH(const fs::path &path, get_image_paths()){ - fs::path image_path = path / image_name; - if (fs::exists(image_path)) return image_path.string(); - } - throw uhd::io_error("Could not find path for image: " + image_name + "\n\n" + uhd::print_images_error()); -} - -std::string uhd::find_images_downloader(void){ - return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "uhd_images_downloader.py").string(); -} - -std::string uhd::print_images_error(void){ - #ifdef UHD_PLATFORM_WIN32 - return "As an Administrator, please run:\n\n\"" + find_images_downloader() + "\""; - #else - return "Please run:\n\nsudo \"" + find_images_downloader() + "\""; - #endif -} diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 3e2bea1c6..282ebb566 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -17,15 +17,19 @@ #include #include -#include + +#include +#include #include #include -#include +#include + +#include //P_tmpdir #include +#include #include #include -#include //getenv -#include //P_tmpdir + #ifdef BOOST_MSVC #define USE_GET_TEMP_PATH #include //GetTempPath @@ -136,3 +140,28 @@ std::string uhd::get_app_path(void){ return uhd::get_tmp_path(); } + +std::string uhd::find_image_path(const std::string &image_name){ + if (fs::exists(image_name)){ + return fs::system_complete(image_name).string(); + } + BOOST_FOREACH(const fs::path &path, get_image_paths()){ + fs::path image_path = path / image_name; + if (fs::exists(image_path)) return image_path.string(); + } + throw uhd::io_error("Could not find path for image: " + image_name + + "\n\n" + uhd::print_utility_error("uhd_images_downloader.py")); +} + +std::string uhd::find_utility(std::string name) { + return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / name) + .string(); +} + +std::string uhd::print_utility_error(std::string name){ + #ifdef UHD_PLATFORM_WIN32 + return "As an Administrator, please run:\n\n\"" + find_utility(name) + "\""; + #else + return "Please run:\n\n \"" + find_utility(name) + "\""; + #endif +} diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index 0cab6618d..8b64be63e 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include namespace po = boost::program_options; namespace fs = boost::filesystem; diff --git a/host/utils/octoclock_firmware_burner.cpp b/host/utils/octoclock_firmware_burner.cpp index 9551ddd20..0a48caabd 100644 --- a/host/utils/octoclock_firmware_burner.cpp +++ b/host/utils/octoclock_firmware_burner.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include diff --git a/host/utils/usrp_n2xx_simple_net_burner.cpp b/host/utils/usrp_n2xx_simple_net_burner.cpp index dc83b6fdf..b06e67bb2 100644 --- a/host/utils/usrp_n2xx_simple_net_burner.cpp +++ b/host/utils/usrp_n2xx_simple_net_burner.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/host/utils/usrp_x3xx_fpga_burner.cpp b/host/utils/usrp_x3xx_fpga_burner.cpp index b849cfb92..abd5815e8 100644 --- a/host/utils/usrp_x3xx_fpga_burner.cpp +++ b/host/utils/usrp_x3xx_fpga_burner.cpp @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From acb76266a9470209128dcfe982bfd33c1545df97 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Fri, 21 Nov 2014 15:08:31 +0100 Subject: multi_usrp: Handle auto_tick_rate properly --- host/lib/usrp/multi_usrp.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'host/lib') diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 0c128dd22..7f27bdc64 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -431,6 +431,9 @@ public: ******************************************************************/ void set_master_clock_rate(double rate, size_t mboard){ if (mboard != ALL_MBOARDS){ + if (_tree->exists(mb_root(mboard) / "auto_tick_rate")) { + _tree->access(mb_root(mboard) / "auto_tick_rate").set(false); + } _tree->access(mb_root(mboard) / "tick_rate").set(rate); return; } -- cgit v1.2.3 From 0da9251e68606dc9cbb3e1d36914cfb95f890ada Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 3 Nov 2014 16:27:08 +0100 Subject: transport: Made CHDR-related routines separate from VRT Our VRT routines have the option to switch, on the fly, between VRLP and CHDR. This adds new CHDR-specific (un-)packers, which can only work with CHDR. --- host/docs/uhd.dox | 1 + host/docs/vrt_chdr.dox | 83 ++++++++++++ host/include/uhd/transport/CMakeLists.txt | 4 +- host/include/uhd/transport/chdr.hpp | 113 +++++++++++++++++ host/include/uhd/transport/vrt_if_packet.hpp | 74 ++++++++++- host/lib/transport/CMakeLists.txt | 1 + host/lib/transport/chdr.cpp | 182 +++++++++++++++++++++++++++ host/tests/CMakeLists.txt | 3 +- host/tests/chdr_test.cpp | 141 +++++++++++++++++++++ 9 files changed, 598 insertions(+), 4 deletions(-) create mode 100644 host/docs/vrt_chdr.dox create mode 100644 host/include/uhd/transport/chdr.hpp create mode 100644 host/lib/transport/chdr.cpp create mode 100644 host/tests/chdr_test.cpp (limited to 'host/lib') diff --git a/host/docs/uhd.dox b/host/docs/uhd.dox index 5b0738969..5cbe51a90 100644 --- a/host/docs/uhd.dox +++ b/host/docs/uhd.dox @@ -11,6 +11,7 @@ Some additional pages on developing UHD are also available here: \li \subpage page_coding \li \subpage page_stream +\li \subpage page_rtp */ // vim:ft=doxygen: diff --git a/host/docs/vrt_chdr.dox b/host/docs/vrt_chdr.dox new file mode 100644 index 000000000..8ab177b21 --- /dev/null +++ b/host/docs/vrt_chdr.dox @@ -0,0 +1,83 @@ +/*! \page page_rtp Radio Transport Protocols + +\tableofcontents + +Radio transport protocols are used to exchange samples (or other items) between host and devices. +If one were to sniff Ethernet traffic between a USRP and a PC, the packets would conform to a +radio transport protocol. + +For USRP devices, two radio transport protocols are relevent: VRT (the VITA Radio Transport protocol) +and CVITA (compressed VITA), also known as CHDR. Generation-3 devices and the B200 use CHDR, the rest +use VRT. + +\section rtp_vrt VRT + +VRT is an open protocol defined by the VITA-49 standard. It was designed for interoperability, +and to allow different device types to work with different software stacks. + +VRT is a very verbose standard, and only a subset is implemented in UHD/USRPs. +The full standard is available from the VITA website: http://www.vita.com . + + +\section rtp_chdr CVITA (CHDR) + +For the third generation of Ettus devices, a new type transport protocol was designed. +It reduces the complexity of the original standard and uses a fixed-length 64-Bit header +for everything except the timestamp. Because this is a "compressed" form of VITA, it +was dubbed "Compressed VITA" (CVITA). The compressed header is called CHDR, which is why +the protocol is often called CHDR itself (pronounced like the cheese "cheddar"). + +By compressing all information into a 64-bit line, the header can efficiently be parsed +in newer FPGAs, where the common streaming protocol is 64-Bit AXI. The first line in a +packet already provides all necessary information to proceed. + +Some CHDR-specific functions can be found in: uhd::transport::vrt::chdr. + +The form of a CVITA packet is the following: + +Address (Bytes) | Length (Bytes) | Payload +----------------|----------------|---------------------------- +0 | 8 | Compressed Header (CHDR) +8 | 8 | Fractional Time (Optional!) +8/16 | - | Data + +If there is no timestamp present, the data starts at address 8, otherwise, it starts at 16. + +The 64 Bits in the compressed header have the following meaning: + +Bits | Meaning +-------|-------------------------------------------------- +63:62 | Packet Type +61 | Has fractional time stamp (1: Yes) +60 | End-of-burst or error flag +59:48 | 12-bit sequence number +47:32 | Total packet length in Bytes +31:0 | Stream ID (SID) + + +The packet type is determined mainly by the first two bits, although +the EOB or error flag are also taken into consideration: + +Bit 63 | Bit 62 | Bit 60 | Packet Type +-------|--------|--------|-------------- +0 | 0 | 0 | Data +0 | 0 | 1 | Data (End-of-burst) +0 | 1 | 0 | Flow Control +1 | 0 | 0 | Command Packet +1 | 1 | 0 | Command Response +1 | 1 | 1 | Command Response (Error) + +\section vrt_tools Tools + +For CHDR, we provide a Wireshark dissector under tools/chdr_dissector. It can be used +for Ethernet links as well as USB (e.g., for the B210). + +\section vrt_code Code + +Relevent code sections for the radio transport layer are: +* uhd::transport::vrt - Namespace for radio transport protocol related functions and definitions +* uhd::transport::vrt::chdr - Sub-namespace specifically for CVITA/CHDR +* uhd::sid_t - Datatype to represent SIDs + +*/ +// vim:ft=doxygen: diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 2118674c6..623c179e9 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2010-2013 Ettus Research LLC +# Copyright 2010-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 @@ -15,11 +15,11 @@ # along with this program. If not, see . # - UHD_INSTALL(FILES bounded_buffer.hpp bounded_buffer.ipp buffer_pool.hpp + chdr.hpp if_addrs.hpp udp_constants.hpp udp_simple.hpp diff --git a/host/include/uhd/transport/chdr.hpp b/host/include/uhd/transport/chdr.hpp new file mode 100644 index 000000000..5e8cd58a9 --- /dev/null +++ b/host/include/uhd/transport/chdr.hpp @@ -0,0 +1,113 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_TRANSPORT_CHDR_HPP +#define INCLUDED_UHD_TRANSPORT_CHDR_HPP + +#include + +namespace uhd{ namespace transport{ namespace vrt{ + +/*! \brief CVITA/CHDR related function + * + * See \ref rtp_chdr for details on the CVITA/CHDR protocol. + * + * All packers take the host format into account. Choose the _le functions + * if the transport uses little endian format (e.g. PCIe) and the _be + * functions if the transport uses big endian format (e.g. Ethernet). + * + * Note 1: All packers assume there to be enough space at the address + * provided by \p packet_buff. See also \ref vrt_pack_contract. + * + * Note 2: All these packers assume the following options without checking them: + * - `if_packet_info.link_type == LINK_TYPE_CHDR` + * - `if_packet_info.has_cid == false` + * - `if_packet_info.has_sid == true` + * - `if_packet_info.has_tsi == false` + * - `if_packet_info.has_tlr == false` + * This relaxes some of \ref vrt_pack_contract, but adds the additional + * constraint that the input data must be CHDR. + * + * In the unpacker, these values will be set accordingly. + */ +namespace chdr{ + + //! The maximum number of 64-bit words in a CVITA header + static const size_t max_if_hdr_words64 = 2; // CHDR + tsf (fractional timestamp) + + /*! + * Pack a CHDR header from metadata (big endian format). + * + * See \ref vrt_pack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \param packet_buff memory to write the packed vrt header + * \param if_packet_info the if packet info (read/write) + */ + UHD_API void if_hdr_pack_be( + boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info + ); + + /*! + * Unpack a CHDR header to metadata (big endian format). + * + * See \ref vrt_unpack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \param packet_buff memory to read the packed vrt header + * \param if_packet_info the if packet info (read/write) + */ + UHD_API void if_hdr_unpack_be( + const boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info + ); + + /*! + * Pack a CHDR header from metadata (little endian format). + * + * See \ref vrt_pack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \param packet_buff memory to write the packed vrt header + * \param if_packet_info the if packet info (read/write) + */ + UHD_API void if_hdr_pack_le( + boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info + ); + + /*! + * Unpack a CHDR header to metadata (little endian format). + * + * See \ref vrt_unpack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \param packet_buff memory to read the packed vrt header + * \param if_packet_info the if packet info (read/write) + */ + UHD_API void if_hdr_unpack_le( + const boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info + ); + +} //namespace chdr + +}}} //namespace uhd::transport::vrt + +#endif /* INCLUDED_UHD_TRANSPORT_CHDR_HPP */ + diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index d16892281..8bc65cdf1 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2013 Ettus Research LLC +// Copyright 2010-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 @@ -52,9 +52,18 @@ namespace vrt{ //packet type enum packet_type_t { + // VRT language: PACKET_TYPE_DATA = 0x0, PACKET_TYPE_IF_EXT = 0x1, PACKET_TYPE_CONTEXT = 0x2, //extension context: has_sid = true + + // CVITA language: + //PACKET_TYPE_DATA = 0x0, // Data + PACKET_TYPE_FC = 0x1, // Flow control + PACKET_TYPE_ACK = 0x1, // Flow control (ack) + PACKET_TYPE_CMD = 0x2, // Command + PACKET_TYPE_RESP = 0x3, // Command response + PACKET_TYPE_ERROR = 0x3, // Command response: Error (the EOB bit is raised in this case) } packet_type; //size fields @@ -65,18 +74,46 @@ namespace vrt{ //header fields size_t packet_count; + //! Asserted for start- or end-of-burst bool sob, eob; + //! This is asserted for command responses that are errors (CHDR only) + bool error; //optional fields + //! Stream ID (SID). See uhd::sid_t bool has_sid; boost::uint32_t sid; + //! Class ID. bool has_cid; boost::uint64_t cid; + //! Integer timestamp bool has_tsi; boost::uint32_t tsi; + //! Fractional timestamp bool has_tsf; boost::uint64_t tsf; + //! Trailer bool has_tlr; boost::uint32_t tlr; }; /*! * Pack a vrt header from metadata (big endian format). + * + * \section vrt_pack_contract Packing contract + * + * \subsection Requirements: + * - packet_buff points to a valid address space with enough space to write + * the entire buffer, regardless of its length. At the very least, it must + * be able to hold an entire header. + * - `if_packet_info` has the following members set to correct values: + * - `has_*` members all set accordingly + * - For every true `has_*` member, the corresponding variable holds a valid + * value (e.g. if `has_sid` is true, `sid` contains a valid SID) + * - `num_payload_bytes` and `num_payload_words32` are both set to the correct values + * + * \subsection Result: + * - `packet_buff` now points to a valid header that can be sent over the transport + * without further modification + * - The following members on `if_packet_info` are set: + * - `num_header_words32` + * - `num_packet_words32` + * * \param packet_buff memory to write the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -87,6 +124,34 @@ namespace vrt{ /*! * Unpack a vrt header to metadata (big endian format). + * + * \section vrt_unpack_contract Unpacking contract + * + * \subsection Requirements + * - `packet_buff` points to a readable address space with a + * CHDR packet, starting at the header. `packet_buff[0]` *must* always + * point to a valid first word of the header. This implies that num_packet_words32 + * must be at least 1. + * - `if_packet_info` has the following members set to correct values: + * - `num_packet_words32`. This means all values `packet_buff[0]` + * through `packet_buff[if_packet_info.num_packet_words32-1]` are + * readable words from this packet. + * - `link_type` + * + * \subsection Result + * - `if_packet_info` now has the following values set to correct values: + * - `packet_type` + * - `num_payload_bytes` + * - `num_payload_words32` + * - `num_header_words32` + * - `has_*` + * - `sob`, `eob`, `error`, `cid`, `sid` (if applicable) + * - `tsf`, `tsi` (if applicable) + * + * \subsection Exceptions + * - If the header is invalid, but the requirements are still met, + * will throw a uhd::value_error. + * * \param packet_buff memory to read the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -97,6 +162,9 @@ namespace vrt{ /*! * Pack a vrt header from metadata (little endian format). + * + * See \ref vrt_pack_contract. + * * \param packet_buff memory to write the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -107,6 +175,9 @@ namespace vrt{ /*! * Unpack a vrt header to metadata (little endian format). + * + * See \ref vrt_unpack_contract. + * * \param packet_buff memory to read the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -124,6 +195,7 @@ namespace vrt{ num_packet_words32(0), packet_count(0), sob(false), eob(false), + error(false), has_sid(false), sid(0), has_cid(false), cid(0), has_tsi(false), tsi(0), diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt index 5920f3d78..9ec8a5c0b 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -129,6 +129,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/if_addrs.cpp ${CMAKE_CURRENT_SOURCE_DIR}/udp_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/nirio_zero_copy.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/chdr.cpp ) # Verbose Debug output for send/recv diff --git a/host/lib/transport/chdr.cpp b/host/lib/transport/chdr.cpp new file mode 100644 index 000000000..47ac961b9 --- /dev/null +++ b/host/lib/transport/chdr.cpp @@ -0,0 +1,182 @@ +// +// 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 . +// + +#include +#include +#include + +//define the endian macros to convert integers +#ifdef BOOST_BIG_ENDIAN + #define BE_MACRO(x) (x) + #define LE_MACRO(x) uhd::byteswap(x) +#else + #define BE_MACRO(x) uhd::byteswap(x) + #define LE_MACRO(x) (x) +#endif + +using namespace uhd::transport::vrt; + +static const boost::uint32_t HDR_FLAG_TSF = (1 << 29); +static const boost::uint32_t HDR_FLAG_EOB = (1 << 28); +static const boost::uint32_t HDR_FLAG_ERROR = (1 << 28); + +/***************************************************************************/ +/* Packing */ +/***************************************************************************/ +/*! Translate the contents of \p if_packet_info into a 32-Bit word and return it. + */ +UHD_INLINE boost::uint32_t _hdr_pack_chdr( + if_packet_info_t &if_packet_info +) { + // Set fields in if_packet_info + if_packet_info.num_header_words32 = 2 + (if_packet_info.has_tsf ? 2 : 0); + if_packet_info.num_packet_words32 = + if_packet_info.num_header_words32 + + if_packet_info.num_payload_words32; + + boost::uint16_t pkt_length = + if_packet_info.num_payload_bytes + (4 * if_packet_info.num_header_words32); + boost::uint32_t chdr = 0 + // 2 Bits: Packet type + | (if_packet_info.packet_type << 30) + // 1 Bit: Has time + | (if_packet_info.has_tsf ? HDR_FLAG_TSF : 0) + // 1 Bit: EOB or Error + | ((if_packet_info.eob or if_packet_info.error) ? HDR_FLAG_EOB : 0) + // 12 Bits: Sequence number + | ((if_packet_info.packet_count & 0xFFF) << 16) + // 16 Bits: Total packet length + | pkt_length; + return chdr; +} + +void chdr::if_hdr_pack_be( + boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info +) { + // Write header and update if_packet_info + packet_buff[0] = BE_MACRO(_hdr_pack_chdr(if_packet_info)); + + // Write SID + packet_buff[1] = BE_MACRO(if_packet_info.sid); + + // Write time + if (if_packet_info.has_tsf) { + packet_buff[2] = BE_MACRO(boost::uint32_t(if_packet_info.tsf >> 32)); + packet_buff[3] = BE_MACRO(boost::uint32_t(if_packet_info.tsf >> 0)); + } +} + +void chdr::if_hdr_pack_le( + boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info +) { + // Write header and update if_packet_info + packet_buff[0] = LE_MACRO(_hdr_pack_chdr(if_packet_info)); + + // Write SID + packet_buff[1] = LE_MACRO(if_packet_info.sid); + + // Write time + if (if_packet_info.has_tsf) { + packet_buff[2] = LE_MACRO(boost::uint32_t(if_packet_info.tsf >> 32)); + packet_buff[3] = LE_MACRO(boost::uint32_t(if_packet_info.tsf >> 0)); + } +} + + +/***************************************************************************/ +/* Unpacking */ +/***************************************************************************/ +UHD_INLINE void _hdr_unpack_chdr( + const boost::uint32_t chdr, + if_packet_info_t &if_packet_info +) { + // Set constant members + if_packet_info.link_type = if_packet_info_t::LINK_TYPE_CHDR; + if_packet_info.has_cid = false; + if_packet_info.has_sid = true; + if_packet_info.has_tsi = false; + if_packet_info.has_tlr = false; + if_packet_info.sob = false; + + // Set configurable members + if_packet_info.has_tsf = bool(chdr & HDR_FLAG_TSF); + if_packet_info.packet_type = if_packet_info_t::packet_type_t((chdr >> 30) & 0x3); + if_packet_info.eob = (if_packet_info.packet_type == if_packet_info_t::PACKET_TYPE_DATA) + && bool(chdr & HDR_FLAG_EOB); + if_packet_info.error = (if_packet_info.packet_type == if_packet_info_t::PACKET_TYPE_RESP) + && bool(chdr & HDR_FLAG_ERROR); + if_packet_info.packet_count = (chdr >> 16) & 0xFFF; + + // Set packet length variables + if (if_packet_info.has_tsf) { + if_packet_info.num_header_words32 = 4; + } else { + if_packet_info.num_header_words32 = 2; + } + size_t pkt_size_bytes = (chdr & 0xFFFF); + size_t pkt_size_word32 = (pkt_size_bytes / 4) + ((pkt_size_bytes % 4) ? 1 : 0); + // Check lengths match: + if (pkt_size_word32 < if_packet_info.num_header_words32) { + throw uhd::value_error("Bad CHDR or invalid packet length"); + } + if (if_packet_info.num_packet_words32 < pkt_size_word32) { + throw uhd::value_error("Bad CHDR or packet fragment"); + } + if_packet_info.num_payload_bytes = pkt_size_bytes - (4 * if_packet_info.num_header_words32); + if_packet_info.num_payload_words32 = pkt_size_word32 - if_packet_info.num_header_words32; +} + +void chdr::if_hdr_unpack_be( + const boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info +) { + // Read header and update if_packet_info + boost::uint32_t chdr = BE_MACRO(packet_buff[0]); + _hdr_unpack_chdr(chdr, if_packet_info); + + // Read SID + if_packet_info.sid = BE_MACRO(packet_buff[1]); + + // Read time (has_tsf was updated earlier) + if (if_packet_info.has_tsf) { + if_packet_info.tsf = 0 + | boost::uint64_t(BE_MACRO(packet_buff[2])) << 32 + | BE_MACRO(packet_buff[3]); + } +} + +void chdr::if_hdr_unpack_le( + const boost::uint32_t *packet_buff, + if_packet_info_t &if_packet_info +) { + // Read header and update if_packet_info + boost::uint32_t chdr = LE_MACRO(packet_buff[0]); + _hdr_unpack_chdr(chdr, if_packet_info); + + // Read SID + if_packet_info.sid = LE_MACRO(packet_buff[1]); + + // Read time (has_tsf was updated earlier) + if (if_packet_info.has_tsf) { + if_packet_info.tsf = 0 + | boost::uint64_t(LE_MACRO(packet_buff[2])) << 32 + | LE_MACRO(packet_buff[3]); + } +} + diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 579fd46ca..829fb8e94 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -27,8 +27,9 @@ SET(test_sources addr_test.cpp buffer_test.cpp byteswap_test.cpp - convert_test.cpp cast_test.cpp + chdr_test.cpp + convert_test.cpp dict_test.cpp error_test.cpp fp_compare_delta_test.cpp diff --git a/host/tests/chdr_test.cpp b/host/tests/chdr_test.cpp new file mode 100644 index 000000000..8893e12e5 --- /dev/null +++ b/host/tests/chdr_test.cpp @@ -0,0 +1,141 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include + +using namespace uhd::transport::vrt; + +static void pack_and_unpack( + if_packet_info_t &if_packet_info_in +){ + // Temp buffer for packed packet + boost::uint32_t packet_buff[2048] = {0}; + + // Check input (must not be lazy) + BOOST_REQUIRE( + (if_packet_info_in.num_payload_words32 == 0 and if_packet_info_in.num_payload_bytes == 0) + or + (if_packet_info_in.num_payload_words32 != 0 and if_packet_info_in.num_payload_bytes != 0) + ); + if (if_packet_info_in.num_payload_words32) { + BOOST_REQUIRE(if_packet_info_in.num_payload_bytes <= 4 * if_packet_info_in.num_payload_words32); + BOOST_REQUIRE(if_packet_info_in.num_payload_bytes > 4*(if_packet_info_in.num_payload_words32-1)); + } + + //pack metadata into a vrt header + chdr::if_hdr_pack_be( + packet_buff, if_packet_info_in + ); + std::cout << std::endl; + boost::uint32_t header_bits = (uhd::ntohx(packet_buff[0]) >> 28); + std::cout << boost::format("header bits = 0b%d%d%d%d") % bool(header_bits & 8) % bool(header_bits & 4) % bool(header_bits & 2) % bool(header_bits & 1) << std::endl; + for (size_t i = 0; i < 5; i++) + { + std::cout << boost::format("packet_buff[%u] = 0x%08x") % i % uhd::ntohx(packet_buff[i]) << std::endl; + } + + if_packet_info_t if_packet_info_out; + // Must be set a-priori as per contract + if_packet_info_out.num_packet_words32 = if_packet_info_in.num_packet_words32; + + //unpack the vrt header back into metadata + chdr::if_hdr_unpack_be( + packet_buff, if_packet_info_out + ); + + //check the the unpacked metadata is the same + BOOST_CHECK_EQUAL(if_packet_info_in.packet_count, if_packet_info_out.packet_count); + BOOST_CHECK_EQUAL(if_packet_info_in.num_header_words32, if_packet_info_out.num_header_words32); + BOOST_CHECK_EQUAL(if_packet_info_in.num_payload_words32, if_packet_info_out.num_payload_words32); + BOOST_CHECK(if_packet_info_out.has_sid); + BOOST_CHECK_EQUAL(if_packet_info_in.sid, if_packet_info_out.sid); + BOOST_CHECK(if_packet_info_out.has_sid); + BOOST_CHECK_EQUAL(if_packet_info_in.has_tsf, if_packet_info_out.has_tsf); + if (if_packet_info_in.has_tsf and if_packet_info_out.has_tsf){ + BOOST_CHECK_EQUAL(if_packet_info_in.tsf, if_packet_info_out.tsf); + } +} + +BOOST_AUTO_TEST_CASE(test_with_chdr){ + if_packet_info_t if_packet_info; + if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_DATA; + if_packet_info.eob = false; + if_packet_info.packet_count = 7; + if_packet_info.has_tsf = true; + if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.sid = 0xAABBCCDD; + if_packet_info.num_payload_words32 = 24; + if_packet_info.num_payload_bytes = 95; + pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_fc){ + if_packet_info_t if_packet_info; + if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_FC; + if_packet_info.eob = false; + if_packet_info.packet_count = 19; + if_packet_info.has_tsf = false; + if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.sid = 0xAABBCCDD; + if_packet_info.num_payload_words32 = 4; + if_packet_info.num_payload_bytes = 16; + pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_cmd){ + if_packet_info_t if_packet_info; + if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_CMD; + if_packet_info.packet_count = 19; + if_packet_info.has_tsf = true; + if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.sid = 0xAABBCCDD; + if_packet_info.num_payload_words32 = 4; + if_packet_info.num_payload_bytes = 16; + pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_resp){ + if_packet_info_t if_packet_info; + if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_RESP; + if_packet_info.packet_count = 123; + if_packet_info.has_tsf = false; + if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.sid = 0xAABBCCDD; + if_packet_info.num_payload_words32 = 4; + if_packet_info.num_payload_bytes = 16; + pack_and_unpack(if_packet_info); +} + +BOOST_AUTO_TEST_CASE(test_with_chdr_err){ + if_packet_info_t if_packet_info; + if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_ERROR; + if_packet_info.packet_count = 1928; + if_packet_info.eob = false; + if_packet_info.error = false; // Needs to be set explicitly + if_packet_info.has_tsf = false; + if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.sid = 0xAABBCCDD; + if_packet_info.num_payload_words32 = 4; + if_packet_info.num_payload_bytes = 16; + pack_and_unpack(if_packet_info); +} + -- cgit v1.2.3 From 2068af70eee6b6ca831d8bd71764d783e182f913 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 4 Nov 2014 22:36:26 +0100 Subject: x300: Made use of new CHDR packing routines --- host/lib/usrp/x300/x300_io_impl.cpp | 52 +++++++------------------------------ 1 file changed, 9 insertions(+), 43 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp index 334ae8168..e3515af0c 100644 --- a/host/lib/usrp/x300/x300_io_impl.cpp +++ b/host/lib/usrp/x300/x300_io_impl.cpp @@ -23,6 +23,7 @@ #include #include "async_packet_handler.hpp" #include +#include #include #include #include @@ -123,41 +124,6 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i, } -/*********************************************************************** - * VITA stuff - **********************************************************************/ -static void x300_if_hdr_unpack_be( - const boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_unpack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_be( - boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_pack_be(packet_buff, if_packet_info); -} - -static void x300_if_hdr_unpack_le( - const boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_unpack_le(packet_buff, if_packet_info); -} - -static void x300_if_hdr_pack_le( - boost::uint32_t *packet_buff, - vrt::if_packet_info_t &if_packet_info -){ - if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR; - return vrt::if_hdr_pack_le(packet_buff, if_packet_info); -} - /*********************************************************************** * RX flow control handler **********************************************************************/ @@ -209,9 +175,9 @@ static void handle_rx_flowctrl(const boost::uint32_t sid, zero_copy_if::sptr xpo //load header if (big_endian) - x300_if_hdr_pack_be(pkt, packet_info); + vrt::chdr::if_hdr_pack_be(pkt, packet_info); else - x300_if_hdr_pack_le(pkt, packet_info); + vrt::chdr::if_hdr_pack_le(pkt, packet_info); //load payload pkt[packet_info.num_header_words32+0] = uhd::htonx(0); @@ -276,12 +242,12 @@ static void handle_tx_async_msgs(boost::shared_ptr guts, zero { if (big_endian) { - x300_if_hdr_unpack_be(packet_buff, if_packet_info); + vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info); endian_conv = uhd::ntohx; } else { - x300_if_hdr_unpack_le(packet_buff, if_packet_info); + vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info); endian_conv = uhd::wtohx; } } @@ -430,10 +396,10 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_) //init some streamer stuff std::string conv_endianness; if (mb.if_pkt_is_big_endian) { - my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_be); + my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be); conv_endianness = "be"; } else { - my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_le); + my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_le); conv_endianness = "le"; } @@ -594,10 +560,10 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_) std::string conv_endianness; if (mb.if_pkt_is_big_endian) { - my_streamer->set_vrt_packer(&x300_if_hdr_pack_be); + my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be); conv_endianness = "be"; } else { - my_streamer->set_vrt_packer(&x300_if_hdr_pack_le); + my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_le); conv_endianness = "le"; } -- cgit v1.2.3 From 12d91d67187e72c189c42970f3bc1323c1977a4a Mon Sep 17 00:00:00 2001 From: Ashish Chaudhari Date: Fri, 5 Dec 2014 09:21:06 -0800 Subject: x300: Fixed minor issues in X300 clk code - Bugfix for #638 - get_ref_locked will check lock status one last time before giving up --- host/lib/usrp/x300/x300_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 8d255097d..c7980c997 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -1434,8 +1434,8 @@ bool x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout) boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } while (boost::get_system_time() < timeout_time); - //failed to lock on reference - return false; + //Check one last time + return get_ref_locked(ctrl).to_bool(); } sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl) -- cgit v1.2.3 From 3c5fe0a201d78a8732aad31a71bf806e00c89db1 Mon Sep 17 00:00:00 2001 From: Ben Hilburn Date: Thu, 18 Dec 2014 15:37:20 -0800 Subject: Adding support for NI VID + PIDs for USRP B2xx devices. --- host/include/uhd/transport/usb_device_handle.hpp | 3 + host/lib/transport/libusb1_base.cpp | 20 +++--- host/lib/usrp/b200/b200_iface.hpp | 3 + host/lib/usrp/b200/b200_impl.cpp | 72 +++++++++++++++++---- host/utils/b2xx_fx3_utils.cpp | 80 ++++++++++++++++-------- 5 files changed, 134 insertions(+), 44 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index fdea9e2be..bf122f549 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -41,6 +41,7 @@ namespace uhd { namespace transport { class UHD_API usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr sptr; + typedef std::pair vid_pid_pair_t; /*! * Return the device's serial number @@ -83,6 +84,8 @@ public: * \return a vector of USB device handles that match vid and pid */ static std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); + static std::vector get_device_list(const std::vector& vid_pid_pair_list); + }; //namespace usb diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index ee4e20adb..18acb1fdc 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -343,15 +343,21 @@ libusb::special_handle::sptr libusb::special_handle::make(device::sptr dev){ std::vector usb_device_handle::get_device_list( boost::uint16_t vid, boost::uint16_t pid ){ - std::vector handles; + return usb_device_handle::get_device_list(std::vector(1,usb_device_handle::vid_pid_pair_t(vid,pid))); +} +std::vector usb_device_handle::get_device_list(const std::vector& vid_pid_pair_list) +{ + std::vector handles; libusb::device_list::sptr dev_list = libusb::device_list::make(); - for (size_t i = 0; i < dev_list->size(); i++){ - usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); - if (handle->get_vendor_id() == vid and handle->get_product_id() == pid){ - handles.push_back(handle); - } + for(size_t iter = 0; iter < vid_pid_pair_list.size(); ++iter) + { + for (size_t i = 0; i < dev_list->size(); i++){ + usb_device_handle::sptr handle = libusb::special_handle::make(dev_list->at(i)); + if (handle->get_vendor_id() == vid_pid_pair_list[iter].first and handle->get_product_id() == vid_pid_pair_list[iter].second){ + handles.push_back(handle); + } + } } - return handles; } diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp index 83adfdd64..1821865d3 100644 --- a/host/lib/usrp/b200/b200_iface.hpp +++ b/host/lib/usrp/b200/b200_iface.hpp @@ -26,7 +26,10 @@ #include "ad9361_ctrl.hpp" const static boost::uint16_t B200_VENDOR_ID = 0x2500; +const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923; const static boost::uint16_t B200_PRODUCT_ID = 0x0020; +const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813; +const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814; const static boost::uint16_t FX3_VID = 0x04b4; const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3; const static boost::uint16_t FX3_REENUM_PID = 0x00f0; diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index b2f0d8d3e..9b323cb13 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -87,14 +87,16 @@ static device_addrs_t b200_find(const device_addr_t &hint) //since an address and resource is intended for a different, non-USB, device. if (hint.has_key("addr") || hint.has_key("resource")) return b200_addrs; - boost::uint16_t vid, pid; + size_t found = 0; + std::vector vid_pid_pair_list;//vid pid pair search list for devices. if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "b200") { - vid = uhd::cast::hexstr_cast(hint.get("vid")); - pid = uhd::cast::hexstr_cast(hint.get("pid")); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(uhd::cast::hexstr_cast(hint.get("vid")), + uhd::cast::hexstr_cast(hint.get("pid")))); } else { - vid = B200_VENDOR_ID; - pid = B200_PRODUCT_ID; + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID)); } // Important note: @@ -104,8 +106,9 @@ static device_addrs_t b200_find(const device_addr_t &hint) // This requirement is a courtesy of libusb1.0 on windows. //find the usrps and load firmware - size_t found = 0; - BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) { + std::vector uhd_usb_device_vector = usb_device_handle::get_device_list(vid_pid_pair_list); + + BOOST_FOREACH(usb_device_handle::sptr handle, uhd_usb_device_vector) { //extract the firmware path for the b200 std::string b200_fw_image; try{ @@ -138,7 +141,7 @@ static device_addrs_t b200_find(const device_addr_t &hint) //search for the device until found or timeout while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0) { - BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) + BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid_pid_pair_list)) { usb_control::sptr control; try{control = usb_control::make(handle, 0);} @@ -155,12 +158,16 @@ static device_addrs_t b200_find(const device_addr_t &hint) { switch (boost::lexical_cast(mb_eeprom["product"])) { + //0x0001 and 0x7737 are Ettus B200 product Ids. case 0x0001: case 0x7737: + case B200_PRODUCT_NI_ID: new_addr["product"] = "B200"; break; - case 0x7738: + //0x0002 and 0x7738 are Ettus B210 product Ids. case 0x0002: + case 0x7738: + case B210_PRODUCT_NI_ID: new_addr["product"] = "B210"; break; default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl; @@ -204,13 +211,50 @@ b200_impl::b200_impl(const device_addr_t &device_addr) //try to match the given device address with something on the USB bus boost::uint16_t vid = B200_VENDOR_ID; boost::uint16_t pid = B200_PRODUCT_ID; + bool specified_vid = false; + bool specified_pid = false; + if (device_addr.has_key("vid")) + { vid = uhd::cast::hexstr_cast(device_addr.get("vid")); + specified_vid = true; + } + if (device_addr.has_key("pid")) + { pid = uhd::cast::hexstr_cast(device_addr.get("pid")); + specified_pid = true; + } + + std::vector vid_pid_pair_list;//search list for devices. - std::vector device_list = - usb_device_handle::get_device_list(vid, pid); + // Search only for specified VID and PID if both specified + if (specified_vid && specified_pid) + { + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,pid)); + } + // Search for all supported PIDs limited to specified VID if only VID specified + else if (specified_vid) + { + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_NI_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B210_PRODUCT_NI_ID)); + } + // Search for all supported VIDs limited to specified PID if only PID specified + else if (specified_pid) + { + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,pid)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,pid)); + } + // Search for all supported devices if neither VID nor PID specified + else + { + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,B200_PRODUCT_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B200_PRODUCT_NI_ID)); + vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B210_PRODUCT_NI_ID)); + } + + std::vector device_list = usb_device_handle::get_device_list(vid_pid_pair_list); //locate the matching handle in the device list usb_device_handle::sptr handle; @@ -244,13 +288,17 @@ b200_impl::b200_impl(const device_addr_t &device_addr) { switch (boost::lexical_cast(mb_eeprom["product"])) { + //0x0001 and 0x7737 are Ettus B200 product Ids. case 0x0001: case 0x7737: + case B200_PRODUCT_NI_ID: product_name = "B200"; default_file_name = B200_FPGA_FILE_NAME; break; - case 0x7738: + //0x0002 and 0x7738 are Ettus B210 product Ids. case 0x0002: + case 0x7738: + case B210_PRODUCT_NI_ID: product_name = "B210"; default_file_name = B210_FPGA_FILE_NAME; break; diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index 8b64be63e..78449a8a4 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -54,17 +54,21 @@ const static vid_pid_t known_vid_pids[] = { {B200_VENDOR_ID, B200_PRODUCT_ID} }; const static std::vector known_vid_pid_vector(known_vid_pids, known_vid_pids + (sizeof(known_vid_pids) / sizeof(known_vid_pids[0]))); -const static boost::uint8_t eeprom_init_values[] = { - 0x43, - 0x59, - 0x14, - 0xB2, - (B200_PRODUCT_ID & 0xff), - (B200_PRODUCT_ID >> 8), - (B200_VENDOR_ID & 0xff), - (B200_VENDOR_ID >> 8) - }; -const static uhd::byte_vector_t eeprom_init_value_vector(eeprom_init_values, eeprom_init_values + (sizeof(eeprom_init_values) / sizeof(eeprom_init_values[0]))); + +static const size_t EEPROM_INIT_VALUE_VECTOR_SIZE = 8; +static uhd::byte_vector_t construct_eeprom_init_value_vector(boost::uint16_t vid, boost::uint16_t pid) +{ + uhd::byte_vector_t init_values(EEPROM_INIT_VALUE_VECTOR_SIZE); + init_values.push_back(0x43); + init_values.push_back(0x59); + init_values.push_back(0x14); + init_values.push_back(0xB2); + init_values.push_back(static_cast(pid & 0xff)); + init_values.push_back(static_cast(pid >> 8)); + init_values.push_back(static_cast(vid & 0xff)); + init_values.push_back(static_cast(vid >> 8)); + return init_values; +} //!used with lexical cast to parse a hex string template struct to_hex{ @@ -153,15 +157,22 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c try { // try caller's VID/PID first - handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); - if (user_supplied && handles.size() == 0) - std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl; - - // try known VID/PIDs next - for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++) + std::vector vid_pid_pair_list(1,uhd::transport::usb_device_handle::vid_pid_pair_t(vid,pid)); + handles = uhd::transport::usb_device_handle::get_device_list(vid_pid_pair_list); + if (handles.size() == 0) { - vp = known_vid_pid_vector[i]; - handles = uhd::transport::usb_device_handle::get_device_list(vp.vid,vp.pid); + if (user_supplied) + { + std::cerr << (boost::format("Failed to open device with VID 0x%04x and PID 0x%04x - trying other known VID/PIDs") % vid % pid).str() << std::endl; + } + + // try known VID/PIDs next + for (size_t i = 0; handles.size() == 0 && i < known_vid_pid_vector.size(); i++) + { + vp = known_vid_pid_vector[i]; + handles = uhd::transport::usb_device_handle::get_device_list(vp.vid, vp.pid); + } + } if (handles.size() > 0) @@ -281,7 +292,7 @@ int erase_eeprom(b200_iface::sptr& b200) boost::int32_t main(boost::int32_t argc, char *argv[]) { boost::uint16_t vid, pid; - std::string pid_str, vid_str, fw_file, fpga_file; + std::string pid_str, vid_str, fw_file, fpga_file, writevid_str, writepid_str; bool user_supplied_vid_pid = false; po::options_description visible("Allowed options"); @@ -295,7 +306,6 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { ("reset-device,D", "Reset the B2xx Device.") ("reset-fpga,F", "Reset the FPGA (does not require re-programming.") ("reset-usb,U", "Reset the USB subsystem on your host computer.") - ("init-device,I", "Initialize a B2xx device.") ("load-fw,W", po::value(&fw_file), "Load a firmware (hex) file into the FX3.") ("load-fpga,L", po::value(&fpga_file), @@ -305,9 +315,14 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { // Hidden options provided for testing - use at your own risk! po::options_description hidden("Hidden options"); hidden.add_options() - ("uninit-device,U", "Uninitialize a B2xx device.") + ("init-device,I", "Initialize a B2xx device.") + ("uninit-device", "Uninitialize a B2xx device.") ("read-eeprom,R", "Read first 8 bytes of EEPROM") - ("erase-eeprom,E", "Erase first 8 bytes of EEPROM"); + ("erase-eeprom,E", "Erase first 8 bytes of EEPROM") + ("write-vid", po::value(&writevid_str), + "Write VID field of EEPROM") + ("write-pid", po::value(&writepid_str), + "Write PID field of EEPROM"); po::options_description desc; desc.add(visible); @@ -486,9 +501,24 @@ boost::int32_t main(boost::int32_t argc, char *argv[]) { * Cypress VID/PID for the initial FW load, but we can initialize from any state. */ if (vm.count("init-device")) { + uint16_t writevid = B200_VENDOR_ID; + uint16_t writepid = B200_PRODUCT_ID; + /* Now, initialize the device. */ - if (write_and_verify_eeprom(b200, eeprom_init_value_vector)) - return -1; + // Added for testing purposes - not exposed + if (vm.count("write-vid") && vm.count("write-pid")) + { + try { + writevid = atoh(writevid_str); + writepid = atoh(writepid_str); + } catch (std::exception &e) { + std::cerr << "Exception while parsing write VID and PID: " << e.what() << std:: endl; + return ~0; + } + } + + std::cout << "Writing VID and PID to EEPROM..." << std::endl << std::endl; + if (write_and_verify_eeprom(b200, construct_eeprom_init_value_vector(writevid, writepid))) return -1; std::cout << "EEPROM initialized, resetting device..." << std::endl << std::endl; -- cgit v1.2.3 From 2ce97f6c05f607846eb11e9799b5d5045049e747 Mon Sep 17 00:00:00 2001 From: Brooks Date: Fri, 19 Dec 2014 10:51:05 -0600 Subject: x300: support new 120 MHz bandwidth versions of the NI-branded X310s --- host/lib/transport/nirio/rpc/rpc_client.cpp | 2 +- host/lib/usrp/x300/x300_impl.cpp | 46 +++++---- host/lib/usrp/x300/x300_regs.hpp | 140 +++++++++++++++------------- 3 files changed, 103 insertions(+), 85 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/nirio/rpc/rpc_client.cpp b/host/lib/transport/nirio/rpc/rpc_client.cpp index cf8e9c1a9..48f47cfae 100644 --- a/host/lib/transport/nirio/rpc/rpc_client.cpp +++ b/host/lib/transport/nirio/rpc/rpc_client.cpp @@ -52,7 +52,7 @@ rpc_client::rpc_client ( //- address_configured: Only return addresses if a non-loopback address is configured for the system. //- numeric_host: No name resolution should be attempted for host //- numeric_service: No name resolution should be attempted for service - tcp::resolver::query::flags query_flags; + tcp::resolver::query::flags query_flags = tcp::resolver::query::passive; tcp::resolver::query query(tcp::v4(), server, port, query_flags); tcp::resolver::iterator iterator = resolver.resolve(query); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index c7980c997..95ac3af38 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -41,7 +41,7 @@ #define NIUSRPRIO_DEFAULT_RPC_PORT "5444" -#define X300_REV(x) (x - "A" + 1) +#define X300_REV(x) ((x) - "A" + 1) using namespace uhd; using namespace uhd::usrp; @@ -1722,14 +1722,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie(const std::string& res case X300_USRP_PCIE_SSID: mb_type = USRP_X300_MB; break; case X310_USRP_PCIE_SSID: - case X310_2940R_PCIE_SSID: - case X310_2942R_PCIE_SSID: - case X310_2943R_PCIE_SSID: - case X310_2944R_PCIE_SSID: - case X310_2950R_PCIE_SSID: - case X310_2952R_PCIE_SSID: - case X310_2953R_PCIE_SSID: - case X310_2954R_PCIE_SSID: + case X310_2940R_40MHz_PCIE_SSID: + case X310_2940R_120MHz_PCIE_SSID: + case X310_2942R_40MHz_PCIE_SSID: + case X310_2942R_120MHz_PCIE_SSID: + case X310_2943R_40MHz_PCIE_SSID: + case X310_2943R_120MHz_PCIE_SSID: + case X310_2944R_40MHz_PCIE_SSID: + case X310_2950R_40MHz_PCIE_SSID: + case X310_2950R_120MHz_PCIE_SSID: + case X310_2952R_40MHz_PCIE_SSID: + case X310_2952R_120MHz_PCIE_SSID: + case X310_2953R_40MHz_PCIE_SSID: + case X310_2953R_120MHz_PCIE_SSID: + case X310_2954R_40MHz_PCIE_SSID: mb_type = USRP_X310_MB; break; default: mb_type = UNKNOWN; break; @@ -1757,14 +1763,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom(const uhd::usrp::mbo case X300_USRP_PCIE_SSID: mb_type = USRP_X300_MB; break; case X310_USRP_PCIE_SSID: - case X310_2940R_PCIE_SSID: - case X310_2942R_PCIE_SSID: - case X310_2943R_PCIE_SSID: - case X310_2944R_PCIE_SSID: - case X310_2950R_PCIE_SSID: - case X310_2952R_PCIE_SSID: - case X310_2953R_PCIE_SSID: - case X310_2954R_PCIE_SSID: + case X310_2940R_40MHz_PCIE_SSID: + case X310_2940R_120MHz_PCIE_SSID: + case X310_2942R_40MHz_PCIE_SSID: + case X310_2942R_120MHz_PCIE_SSID: + case X310_2943R_40MHz_PCIE_SSID: + case X310_2943R_120MHz_PCIE_SSID: + case X310_2944R_40MHz_PCIE_SSID: + case X310_2950R_40MHz_PCIE_SSID: + case X310_2950R_120MHz_PCIE_SSID: + case X310_2952R_40MHz_PCIE_SSID: + case X310_2952R_120MHz_PCIE_SSID: + case X310_2953R_40MHz_PCIE_SSID: + case X310_2953R_120MHz_PCIE_SSID: + case X310_2954R_40MHz_PCIE_SSID: mb_type = USRP_X310_MB; break; default: UHD_MSG(warning) << "X300 unknown product code in EEPROM: " << product_num << std::endl; diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index f920b5ae2..68f438b7f 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -25,40 +25,40 @@ #define localparam static const int -localparam SR_DACSYNC = 5; -localparam SR_LOOPBACK = 6; -localparam SR_TEST = 7; -localparam SR_SPI = 8; -localparam SR_GPIO = 16; -localparam SR_MISC_OUTS = 24; -localparam SR_READBACK = 32; -localparam SR_TX_CTRL = 64; -localparam SR_RX_CTRL = 96; -localparam SR_TIME = 128; -localparam SR_RX_DSP = 144; -localparam SR_TX_DSP = 184; -localparam SR_LEDS = 195; -localparam SR_FP_GPIO = 200; -localparam SR_RX_FRONT = 208; -localparam SR_TX_FRONT = 216; - -localparam RB32_GPIO = 0; -localparam RB32_SPI = 4; -localparam RB64_TIME_NOW = 8; -localparam RB64_TIME_PPS = 16; -localparam RB32_TEST = 24; -localparam RB32_RX = 28; -localparam RB32_FP_GPIO = 32; - -localparam BL_ADDRESS = 0; -localparam BL_DATA = 1; +localparam SR_DACSYNC = 5; +localparam SR_LOOPBACK = 6; +localparam SR_TEST = 7; +localparam SR_SPI = 8; +localparam SR_GPIO = 16; +localparam SR_MISC_OUTS = 24; +localparam SR_READBACK = 32; +localparam SR_TX_CTRL = 64; +localparam SR_RX_CTRL = 96; +localparam SR_TIME = 128; +localparam SR_RX_DSP = 144; +localparam SR_TX_DSP = 184; +localparam SR_LEDS = 196; +localparam SR_FP_GPIO = 200; +localparam SR_RX_FRONT = 208; +localparam SR_TX_FRONT = 216; + +localparam RB32_GPIO = 0; +localparam RB32_SPI = 4; +localparam RB64_TIME_NOW = 8; +localparam RB64_TIME_PPS = 16; +localparam RB32_TEST = 24; +localparam RB32_RX = 28; +localparam RB32_FP_GPIO = 32; + +localparam BL_ADDRESS = 0; +localparam BL_DATA = 1; //wishbone settings map - relevant to host code -#define SET0_BASE 0xa000 -#define SETXB_BASE 0xb000 -#define BOOT_LDR_BASE 0xFA00 -#define I2C0_BASE 0xfe00 -#define I2C1_BASE 0xff00 +#define SET0_BASE 0xa000 +#define SETXB_BASE 0xb000 +#define BOOT_LDR_BASE 0xfa00 +#define I2C0_BASE 0xfe00 +#define I2C1_BASE 0xff00 #define SR_ADDR(base, offset) ((base) + (offset)*4) localparam ZPU_SR_LEDS = 00; @@ -70,56 +70,62 @@ localparam ZPU_SR_ETHINT0 = 40; localparam ZPU_SR_ETHINT1 = 56; //clock controls -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02 -#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02 -#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03 - -localparam ZPU_RB_SPI = 2; +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02 +#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03 + +localparam ZPU_RB_SPI = 2; localparam ZPU_RB_CLK_STATUS = 3; localparam ZPU_RB_COMPAT_NUM = 6; localparam ZPU_RB_ETH_TYPE0 = 4; localparam ZPU_RB_ETH_TYPE1 = 5; //clock status -#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0) -#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2) -#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3) -#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4) +#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0) +#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2) +#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3) +#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4) //spi slaves on radio -#define DB_DAC_SEN (1 << 7) -#define DB_ADC_SEN (1 << 6) +#define DB_DAC_SEN (1 << 7) +#define DB_ADC_SEN (1 << 6) #define DB_RX_LSADC_SEN (1 << 5) #define DB_RX_LSDAC_SEN (1 << 4) #define DB_TX_LSADC_SEN (1 << 3) #define DB_TX_LSDAC_SEN (1 << 2) -#define DB_RX_SEN (1 << 1) -#define DB_TX_SEN (1 << 0) +#define DB_RX_SEN (1 << 1) +#define DB_TX_SEN (1 << 0) //------------------------------------------------------------------- // PCIe Registers //------------------------------------------------------------------- -static const uint32_t X300_PCIE_VID = 0x1093; -static const uint32_t X300_PCIE_PID = 0xC4C4; -static const uint32_t X300_USRP_PCIE_SSID = 0x7736; -static const uint32_t X310_USRP_PCIE_SSID = 0x76CA; -static const uint32_t X310_2940R_PCIE_SSID = 0x772B; -static const uint32_t X310_2942R_PCIE_SSID = 0x772C; -static const uint32_t X310_2943R_PCIE_SSID = 0x772D; -static const uint32_t X310_2944R_PCIE_SSID = 0x772E; -static const uint32_t X310_2950R_PCIE_SSID = 0x772F; -static const uint32_t X310_2952R_PCIE_SSID = 0x7730; -static const uint32_t X310_2953R_PCIE_SSID = 0x7731; -static const uint32_t X310_2954R_PCIE_SSID = 0x7732; +static const uint32_t X300_PCIE_VID = 0x1093; +static const uint32_t X300_PCIE_PID = 0xC4C4; +static const uint32_t X300_USRP_PCIE_SSID = 0x7736; +static const uint32_t X310_USRP_PCIE_SSID = 0x76CA; +static const uint32_t X310_2940R_40MHz_PCIE_SSID = 0x772B; +static const uint32_t X310_2940R_120MHz_PCIE_SSID = 0x77FB; +static const uint32_t X310_2942R_40MHz_PCIE_SSID = 0x772C; +static const uint32_t X310_2942R_120MHz_PCIE_SSID = 0x77FC; +static const uint32_t X310_2943R_40MHz_PCIE_SSID = 0x772D; +static const uint32_t X310_2943R_120MHz_PCIE_SSID = 0x77FD; +static const uint32_t X310_2944R_40MHz_PCIE_SSID = 0x772E; +static const uint32_t X310_2950R_40MHz_PCIE_SSID = 0x772F; +static const uint32_t X310_2950R_120MHz_PCIE_SSID = 0x77FE; +static const uint32_t X310_2952R_40MHz_PCIE_SSID = 0x7730; +static const uint32_t X310_2952R_120MHz_PCIE_SSID = 0x77FF; +static const uint32_t X310_2953R_40MHz_PCIE_SSID = 0x7731; +static const uint32_t X310_2953R_120MHz_PCIE_SSID = 0x7800; +static const uint32_t X310_2954R_40MHz_PCIE_SSID = 0x7732; static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030; static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000; -#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + X) +#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X)) static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000); static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004); @@ -140,8 +146,8 @@ static const uint32_t DMA_FRAME_SIZE_REG = 0x4; static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8; static const uint32_t DMA_PKT_COUNT_REG = 0xC; -#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) -#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG) +#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) +#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG)) static const uint32_t DMA_CTRL_DISABLED = 0x00000000; static const uint32_t DMA_CTRL_ENABLED = 0x00000002; @@ -154,15 +160,15 @@ static const uint32_t DMA_STATUS_ERROR = 0x00000001; static const uint32_t DMA_STATUS_BUSY = 0x00000002; static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500); -#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + X) +#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X)) static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000; static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; //Trig and Status share the same base static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000; -#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + X) -#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + X) -#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + X) +#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X)) +#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X)) +#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X)) static const uint32_t PCIE_ZPU_READ_START = 0x0; static const uint32_t PCIE_ZPU_READ_CLOBBER = 0x80000000; -- cgit v1.2.3 From f88b10d6b4824a8df5834414d684e5cca0544d3d Mon Sep 17 00:00:00 2001 From: Brooks Prumo Date: Mon, 5 Jan 2015 10:39:38 -0600 Subject: revert unnecessary change to the SR_LEDS --- host/lib/usrp/x300/x300_regs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp index 68f438b7f..4c5729efe 100644 --- a/host/lib/usrp/x300/x300_regs.hpp +++ b/host/lib/usrp/x300/x300_regs.hpp @@ -37,7 +37,7 @@ localparam SR_RX_CTRL = 96; localparam SR_TIME = 128; localparam SR_RX_DSP = 144; localparam SR_TX_DSP = 184; -localparam SR_LEDS = 196; +localparam SR_LEDS = 195; localparam SR_FP_GPIO = 200; localparam SR_RX_FRONT = 208; localparam SR_TX_FRONT = 216; -- cgit v1.2.3 From 3f9ef46bc51acc5933721974e191d2a9659f6566 Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Fri, 19 Dec 2014 14:52:57 -0800 Subject: Added support for MinGW cross-compile * Added CMake toolchain file, compatible with different versions * No dependency on MinGW runtime, all statically linked * Misc coding tweaks to allow MinGW to compile --- host/CMakeLists.txt | 16 +++++ host/cmake/Toolchains/mingw_cross.cmake | 69 ++++++++++++++++++++++ host/include/uhd/config.hpp | 9 ++- .../uhd/transport/nirio/nirio_driver_iface.h | 4 +- host/lib/transport/nirio/nifpga_lvbitx.cpp | 2 +- host/lib/utils/platform.cpp | 4 +- host/tests/CMakeLists.txt | 8 ++- 7 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 host/cmake/Toolchains/mingw_cross.cmake (limited to 'host/lib') diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 856f1ec70..6d87bf95d 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -137,6 +137,22 @@ IF(MSVC) ADD_DEFINITIONS(/MP) #multi-threaded build ENDIF(MSVC) +IF(MINGW) + #Avoid depending on MinGW runtime DLLs + CHECK_CXX_COMPILER_FLAG(-static-libgcc HAVE_STATIC_LIBGCC_FLAG) + IF(HAVE_STATIC_LIBGCC_FLAG) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc") + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libgcc") + ENDIF() + CHECK_CXX_COMPILER_FLAG(-static-libstdc++ HAVE_STATIC_LIBSTDCXX_FLAG) + IF(HAVE_STATIC_LIBSTDCXX_FLAG) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++") + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++") + SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -static-libstdc++") + ENDIF() +ENDIF() + IF(CYGWIN) ADD_DEFINITIONS(-D__USE_W32_SOCKETS) #boost asio says we need this ENDIF(CYGWIN) diff --git a/host/cmake/Toolchains/mingw_cross.cmake b/host/cmake/Toolchains/mingw_cross.cmake new file mode 100644 index 000000000..7c5adb002 --- /dev/null +++ b/host/cmake/Toolchains/mingw_cross.cmake @@ -0,0 +1,69 @@ +# Use this command: +# +# cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw.cmake . +# +# or for out of source: +# +# cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw.cmake .. +# +# You will need at least CMake 2.6.0. +# +# Adjust the following paths to suit your environment. +# +# This file was based on http://www.cmake.org/Wiki/CmakeMingw + +# the name of the target operating system +set(CMAKE_SYSTEM_NAME Windows) + +# Assume the target architecture. +# XXX for some reason the value set here gets cleared before we reach the +# main CMakeLists.txt; see that file for a workaround. +# set(CMAKE_SYSTEM_PROCESSOR i686) + +# Which compilers to use for C and C++, and location of target +# environment. +if(EXISTS /usr/i586-mingw32msvc) + # First look in standard location as used by Debian/Ubuntu/etc. + set(CMAKE_C_COMPILER i586-mingw32msvc-gcc) + set(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) + set(CMAKE_RC_COMPILER i586-mingw32msvc-windres) + set(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) +elseif(EXISTS /usr/i686-w64-mingw32) + # First look in standard location as used by Debian/Ubuntu/etc. + set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) + set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) + set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) + set(CMAKE_AR:FILEPATH /usr/bin/i686-w64-mingw32-ar) +elseif(EXISTS /opt/mingw) + # You can get a MinGW environment using the script at . + # It downloads and builds MinGW and most of the dependencies for you. + # You can use the toolchain file generated by MXE called `mxe-conf.cmake' + # or you can use this file by adjusting the above and following paths. + set(CMAKE_C_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-gcc) + set(CMAKE_CXX_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-g++) + set(CMAKE_RC_COMPILER /opt/mingw/usr/bin/i686-pc-mingw32-windres) + set(CMAKE_FIND_ROOT_PATH /opt/mingw/usr/i686-pc-mingw32) +else() + # Else fill in local path which the user will likely adjust. + # This is the location assumed by + set(CMAKE_C_COMPILER /usr/local/cross-tools/bin/i386-mingw32-gcc) + set(CMAKE_CXX_COMPILER /usr/local/cross-tools/bin/i386-mingw32-g++) + set(CMAKE_RC_COMPILER /usr/local/cross-tools/bin/i386-mingw32-windres) + set(CMAKE_FIND_ROOT_PATH /usr/local/cross-tools) +endif() + +# Adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Tell pkg-config not to look at the target environment's .pc files. +# Setting PKG_CONFIG_LIBDIR sets the default search directory, but we have to +# set PKG_CONFIG_PATH as well to prevent pkg-config falling back to the host's +# path. +set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) +set(ENV{PKG_CONFIG_PATH} ${CMAKE_FIND_ROOT_PATH}/lib/pkgconfig) + +set(ENV{MINGDIR} ${CMAKE_FIND_ROOT_PATH}) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 619bd0787..173845fea 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2011,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 @@ -56,6 +56,13 @@ typedef ptrdiff_t ssize_t; #define UHD_DEPRECATED __declspec(deprecated) #define UHD_ALIGNED(x) __declspec(align(x)) #define UHD_UNUSED(x) x +#elif defined(__MINGW32__) + #define UHD_EXPORT __declspec(dllexport) + #define UHD_IMPORT __declspec(dllimport) + #define UHD_INLINE inline + #define UHD_DEPRECATED __declspec(deprecated) + #define UHD_ALIGNED(x) __declspec(align(x)) + #define UHD_UNUSED(x) x #elif defined(__GNUG__) && __GNUG__ >= 4 #define UHD_EXPORT __attribute__((visibility("default"))) #define UHD_IMPORT __attribute__((visibility("default"))) diff --git a/host/include/uhd/transport/nirio/nirio_driver_iface.h b/host/include/uhd/transport/nirio/nirio_driver_iface.h index 83afd816a..3e0e56a7f 100644 --- a/host/include/uhd/transport/nirio/nirio_driver_iface.h +++ b/host/include/uhd/transport/nirio/nirio_driver_iface.h @@ -24,9 +24,9 @@ #include #include #if defined(UHD_PLATFORM_WIN32) - #include + #include #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union - #include + #include #pragma warning(default:4201) #elif !defined(UHD_PLATFORM_LINUX) #include diff --git a/host/lib/transport/nirio/nifpga_lvbitx.cpp b/host/lib/transport/nirio/nifpga_lvbitx.cpp index b87d87a8d..189037163 100644 --- a/host/lib/transport/nirio/nifpga_lvbitx.cpp +++ b/host/lib/transport/nirio/nifpga_lvbitx.cpp @@ -115,7 +115,7 @@ std::string nifpga_lvbitx::_get_fpga_images_dir(const std::string search_paths) // directories searched for a LVBITX image. // char* uhd_images_dir; -#ifdef UHD_PLATFORM_WIN32 +#if defined(UHD_PLATFORM_WIN32) && !defined(__MINGW32__) // Some versions of MinGW don't expose _dupenv_s size_t len; errno_t err = _dupenv_s(&uhd_images_dir, &len, "UHD_IMAGES_DIR"); if(not err and uhd_images_dir != NULL) search_path_vtr.push_back(std::string(uhd_images_dir)); diff --git a/host/lib/utils/platform.cpp b/host/lib/utils/platform.cpp index e2f92039e..a9cef663b 100644 --- a/host/lib/utils/platform.cpp +++ b/host/lib/utils/platform.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2012 Ettus Research LLC +// Copyright 2010-2012,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 @@ -19,7 +19,7 @@ #include #include #ifdef UHD_PLATFORM_WIN32 -#include +#include #else #include #endif diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 829fb8e94..596ab1017 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -48,7 +48,11 @@ SET(test_sources ) #turn each test cpp file into an executable with an int main() function -ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) +IF(MINGW) + ADD_DEFINITIONS(-DBOOST_TEST_MAIN) +ELSE() + ADD_DEFINITIONS(-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN) +ENDIF() SET(UHD_TEST_TARGET_DEPS uhd) SET(UHD_TEST_LIBRARY_DIRS ${Boost_LIBRARY_DIRS}) @@ -57,7 +61,7 @@ SET(UHD_TEST_LIBRARY_DIRS ${Boost_LIBRARY_DIRS}) FOREACH(test_source ${test_sources}) GET_FILENAME_COMPONENT(test_name ${test_source} NAME_WE) ADD_EXECUTABLE(${test_name} ${test_source}) - TARGET_LINK_LIBRARIES(${test_name} uhd) + TARGET_LINK_LIBRARIES(${test_name} uhd ${Boost_LIBRARIES}) UHD_ADD_TEST(${test_name} ${test_name}) UHD_INSTALL(TARGETS ${test_name} RUNTIME DESTINATION ${PKG_LIB_DIR}/tests COMPONENT tests) ENDFOREACH(test_source) -- cgit v1.2.3 From 47562bbf143889197f942168173ae7eb99209f19 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Tue, 20 Jan 2015 08:55:08 -0800 Subject: ad9361: Added relative temperature sensor This allows to read a relative temperature from an AD9361 device. --- host/lib/usrp/common/ad9361_ctrl.cpp | 6 +++ host/lib/usrp/common/ad9361_ctrl.hpp | 3 ++ .../usrp/common/ad9361_driver/ad9361_device.cpp | 46 +++++++++++++++++++++- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 7 ++++ 4 files changed, 61 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index 85510530d..3db6739e7 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -172,6 +172,12 @@ public: return sensor_value_t("RSSI", _device.get_rssi(chain), "dB"); } + //! read the internal temp sensor. Average over 3 results + sensor_value_t get_temperature() + { + return sensor_value_t("temp", _device.get_average_temperature(), "C"); + } + private: static ad9361_device_t::direction_t _get_direction_from_antenna(const std::string& antenna) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index 16e1d23eb..7d44700fe 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -100,6 +100,9 @@ public: //! read internal RSSI sensor virtual sensor_value_t get_rssi(const std::string &which) = 0; + + //! read the internal temp sensor + virtual sensor_value_t get_temperature() = 0; }; }} diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 7e574920a..ba8fe1f20 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1485,7 +1485,7 @@ void ad9361_device_t::initialize() /* Setup AuxADC */ _io_iface->poke8(0x00B, 0x00); // Temp Sensor Setup (Offset) _io_iface->poke8(0x00C, 0x00); // Temp Sensor Setup (Temp Window) - _io_iface->poke8(0x00D, 0x03); // Temp Sensor Setup (Periodic Measure) + _io_iface->poke8(0x00D, 0x00); // Temp Sensor Setup (Manual Measure) _io_iface->poke8(0x00F, 0x04); // Temp Sensor Setup (Decimation) _io_iface->poke8(0x01C, 0x10); // AuxADC Setup (Clock Div) _io_iface->poke8(0x01D, 0x01); // AuxADC Setup (Decimation/Enable) @@ -1946,4 +1946,48 @@ double ad9361_device_t::get_rssi(chain_t chain) return rssi; } +/* + * Returns the reading of the internal temperature sensor. + * One point calibration of the sensor was done according to datasheet + * leading to the given default constant correction factor. + */ +double ad9361_device_t::_get_temperature(const double cal_offset, const double timeout) +{ + //set 0x01D[0] to 1 to disable AuxADC GPIO reading + boost::uint8_t tmp = 0; + tmp = _io_iface->peek8(0x01D); + _io_iface->poke8(0x01D, (tmp | 0x01)); + _io_iface->poke8(0x00B, 0); //set offset to 0 + + _io_iface->poke8(0x00C, 0x01); //start reading, clears bit 0x00C[1] + boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time(); + boost::posix_time::time_duration elapsed; + //wait for valid data (toggle of bit 1 in 0x00C) + while(((_io_iface->peek8(0x00C) >> 1) & 0x01) == 0) { + boost::this_thread::sleep(boost::posix_time::microseconds(100)); + elapsed = boost::posix_time::microsec_clock::local_time() - start_time; + if(elapsed.total_milliseconds() > (timeout*1000)) + { + throw uhd::runtime_error("[ad9361_device_t] timeout while reading temperature"); + } + } + _io_iface->poke8(0x00C, 0x00); //clear read flag + + boost::uint8_t temp = _io_iface->peek8(0x00E); //read temperature. + double tmp_temp = temp/1.140f; //according to ADI driver + tmp_temp = tmp_temp + cal_offset; //Constant offset acquired by one point calibration. + + return tmp_temp; +} + +double ad9361_device_t::get_average_temperature(const double cal_offset, const size_t num_samples) +{ + double d_temp = 0; + for(size_t i = 0; i < num_samples; i++) { + double tmp_temp = _get_temperature(cal_offset); + d_temp += (tmp_temp/num_samples); + } + return d_temp; +} + }} diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index fead90424..b178e46cc 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -66,6 +66,12 @@ public: /* Read back the internal RSSI measurement data. */ double get_rssi(chain_t chain); + /*! Read the internal temperature sensor + *\param calibrate return raw sensor readings or apply calibration factor. + *\param num_samples number of measurements to average over + */ + double get_average_temperature(const double cal_offset = -30.0, const size_t num_samples = 3); + //Constants static const double AD9361_MAX_GAIN; static const double AD9361_MAX_CLOCK_RATE; @@ -95,6 +101,7 @@ private: //Methods void _reprogram_gains(); double _tune_helper(direction_t direction, const double value); double _setup_rates(const double rate); + double _get_temperature(const double cal_offset, const double timeout = 0.1); private: //Members typedef struct { -- cgit v1.2.3 From 93bd61a0fec4ea7e81ba78f62fb998116266ac96 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Tue, 20 Jan 2015 08:55:37 -0800 Subject: b200: Expose temperature sensor through property tree (sensors/temp) --- host/lib/usrp/b200/b200_impl.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 8ea50296f..22e68c4ed 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -710,6 +710,8 @@ void b200_impl::setup_radio(const size_t dspno) .set(B200_DEFAULT_FREQ); _tree->create(rf_fe_path / "freq" / "range") .publish(boost::bind(&ad9361_ctrl::get_rf_freq_range)); + _tree->create(rf_fe_path / "sensors" / "temp") + .publish(boost::bind(&ad9361_ctrl::get_temperature, _codec_ctrl)); //setup RX related stuff if (key[0] == 'R') -- cgit v1.2.3 From 81f08ddff55fb5b181fb2575bd418eee2ac95937 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Wed, 10 Dec 2014 12:08:40 -0800 Subject: e200: Expose temperature sensor through property tree (sensors/temp) --- host/lib/usrp/e300/e300_impl.cpp | 2 ++ host/lib/usrp/e300/e300_network.cpp | 2 ++ host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 12 +++++++++++- host/lib/usrp/e300/e300_remote_codec_ctrl.hpp | 2 ++ 4 files changed, 17 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 3f1b4fea4..9b98e6f8b 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -1044,6 +1044,8 @@ void e300_impl::_setup_radio(const size_t dspno) _tree->create(rf_fe_path / "sensors"); //empty TODO _tree->create(rf_fe_path / "sensors" / "lo_locked") .publish(boost::bind(&e300_impl::_get_fe_pll_lock, this, direction == "tx")); + _tree->create(rf_fe_path / "sensors" / "temp") + .publish(boost::bind(&ad9361_ctrl::get_temperature, _codec_ctrl)); BOOST_FOREACH(const std::string &name, ad9361_ctrl::get_gain_names(key)) { _tree->create(rf_fe_path / "gains" / name / "range") diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 189dba838..1ebb8a2ad 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -226,6 +226,8 @@ static void e300_codec_ctrl_tunnel( break; case codec_xact_t::ACTION_GET_RSSI: out->rssi = _codec_ctrl->get_rssi(which_str).to_real(); + case codec_xact_t::ACTION_GET_TEMPERATURE: + out->temp = _codec_ctrl->get_temperature().to_real(); break; default: UHD_MSG(status) << "Got unknown request?!" << std::endl; diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index ed8131e2f..0ea837a85 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -116,10 +116,20 @@ public: _args.bits = uhd::htonx(0); _transact(); - return sensor_value_t("RSSI", _retval.rssi, "dB"); } + sensor_value_t get_temperature() + { + _clear(); + _args.action = uhd::htonx(transaction_t::ACTION_GET_TEMPERATURE); + _args.which = uhd::htonx(transaction_t::CHAIN_NONE); /*Unused*/ + _args.bits = uhd::htonx(0); + + _transact(); + return sensor_value_t("temp", _retval.temp, "C"); + } + private: void _transact() { { diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp index cbc4b52d2..d92e9bd58 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp @@ -34,6 +34,7 @@ public: double gain; double freq; double rssi; + double temp; boost::uint64_t bits; }; @@ -44,6 +45,7 @@ public: static const boost::uint32_t ACTION_TUNE = 13; static const boost::uint32_t ACTION_SET_LOOPBACK = 14; static const boost::uint32_t ACTION_GET_RSSI = 15; + static const boost::uint32_t ACTION_GET_TEMPERATURE = 16; //Values for "which" static const boost::uint32_t CHAIN_NONE = 0; -- cgit v1.2.3 From bee57ee03fd4b9dac476da7e375ddd8dcc749b1b Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 15 Jan 2015 14:37:47 +0100 Subject: convert: Modifications to id_type - Converter ID symbols are exported - to_string() function for lighter feedback --- host/include/uhd/convert.hpp | 3 ++- host/lib/convert/convert_impl.cpp | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index d740d80fb..e42123b20 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -63,12 +63,13 @@ namespace uhd{ namespace convert{ typedef int priority_type; //! Identify a conversion routine in the registry - struct id_type : boost::equality_comparable{ + struct UHD_API id_type : boost::equality_comparable{ std::string input_format; size_t num_inputs; std::string output_format; size_t num_outputs; std::string to_pp_string(void) const; + std::string to_string(void) const; }; //! Implement equality_comparable interface diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 329e94a4d..48eb1f8d6 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -43,10 +43,10 @@ bool convert::operator==(const convert::id_type &lhs, const convert::id_type &rh std::string convert::id_type::to_pp_string(void) const{ return str(boost::format( "conversion ID\n" - " Input format: %s\n" - " Num inputs: %d\n" + " Input format: %s\n" + " Num inputs: %d\n" " Output format: %s\n" - " Num outputs: %d\n" + " Num outputs: %d\n" ) % this->input_format % this->num_inputs @@ -55,6 +55,15 @@ std::string convert::id_type::to_pp_string(void) const{ ); } +std::string convert::id_type::to_string(void) const{ + return str(boost::format("%s (%d) -> %s (%d)") + % this->input_format + % this->num_inputs + % this->output_format + % this->num_outputs + ); +} + /*********************************************************************** * Setup the table registry **********************************************************************/ -- cgit v1.2.3 From ebe7169dcecd1b6899734cefdf5771612067fd48 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 15 Jan 2015 16:44:50 +0100 Subject: convert: Added logging point in get_converter() --- host/lib/convert/convert_impl.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 48eb1f8d6..fd6c8497e 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -101,7 +101,15 @@ convert::function_type convert::get_converter( //find a matching priority priority_type best_prio = -1; BOOST_FOREACH(priority_type prio_i, get_table()[id].keys()){ - if (prio_i == prio) return get_table()[id][prio]; + if (prio_i == prio) { + //----------------------------------------------------------------// + UHD_LOGV(always) << "get_converter: For converter ID: " << id.to_pp_string() << std::endl + << "Using prio: " << prio << std::endl + << std::endl + ; + //----------------------------------------------------------------// + return get_table()[id][prio]; + } best_prio = std::max(best_prio, prio_i); } @@ -109,6 +117,13 @@ convert::function_type convert::get_converter( if (prio != -1) throw uhd::key_error( "Cannot find a conversion routine [with prio] for " + id.to_pp_string()); + //----------------------------------------------------------------// + UHD_LOGV(always) << "get_converter: For converter ID: " << id.to_pp_string() << std::endl + << "Using prio: " << best_prio << std::endl + << std::endl + ; + //----------------------------------------------------------------// + //otherwise, return best prio return get_table()[id][best_prio]; } -- cgit v1.2.3 From 1d1976c48e8ca698d9c35636823c8ea39dc69129 Mon Sep 17 00:00:00 2001 From: mcrymble Date: Fri, 6 Feb 2015 16:10:24 -0600 Subject: b200: Bugfix#692: b200_find now returns an empty device vector when hint contains addr0/resource0/etc style keys. --- host/lib/usrp/b200/b200_impl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 355d12d12..13169a5ed 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -86,7 +86,9 @@ static device_addrs_t b200_find(const device_addr_t &hint) //Return an empty list of addresses when an address or resource is specified, //since an address and resource is intended for a different, non-USB, device. - if (hint.has_key("addr") || hint.has_key("resource")) return b200_addrs; + BOOST_FOREACH(device_addr_t hint_i, separate_device_addr(hint)) { + if (hint_i.has_key("addr") || hint_i.has_key("resource")) return b200_addrs; + } boost::uint16_t vid, pid; -- cgit v1.2.3 From 7d97ab60012b99ed92fb122a3a68d68515a404fa Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 3 Feb 2015 17:20:09 +0100 Subject: multi_usrp: Added a normalized gain setting Adds more methods: {set,get}_normalized_{tx,rx}_gain() which allow changing and reading back the gain within [0, 1]. --- host/include/uhd/usrp/multi_usrp.hpp | 57 ++++++++++++++++++++++++++++++++++++ host/lib/usrp/multi_usrp.cpp | 51 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) (limited to 'host/lib') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 2362ebcd7..cebfda5a2 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -26,6 +26,7 @@ #define UHD_USRP_MULTI_USRP_BW_RANGE_API #define UHD_USRP_MULTI_USRP_USER_REGS_API #define UHD_USRP_MULTI_USRP_GET_USRP_INFO_API +#define UHD_USRP_MULTI_USRP_NORMALIZED_GAIN #include #include @@ -494,6 +495,24 @@ public: return this->set_rx_gain(gain, ALL_GAINS, chan); } + /*! + * Set the normalized RX gain value. + * + * The normalized gain is a value in [0, 1], where 0 is the + * smallest gain value available, and 1 is the largest, independent + * of the device. In between, gains are linearly interpolated. + * + * Check the individual device manual for notes on the gain range. + * + * Note that it is not possible to specify a gain name for + * this function, it will always set the overall gain. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual void set_normalized_rx_gain(double gain, size_t chan = 0) = 0; + /*! * Get the RX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -508,6 +527,19 @@ public: return this->get_rx_gain(ALL_GAINS, chan); } + /*! + * Return the normalized RX gain value. + * + * See set_normalized_rx_gain() for a discussion of normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \returns The normalized gain (in [0, 1]) + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual double get_normalized_rx_gain(size_t chan = 0) = 0; + /*! * Get the RX gain range for the specified gain element. * For an empty name, calculate the overall gain range. @@ -732,6 +764,18 @@ public: return this->set_tx_gain(gain, ALL_GAINS, chan); } + /*! + * Set the normalized TX gain value. + * + * See set_normalized_rx_gain() for a discussion on normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual void set_normalized_tx_gain(double gain, size_t chan = 0) = 0; + /*! * Get the TX gain value for the specified gain element. * For an empty name, sum across all gain elements. @@ -746,6 +790,19 @@ public: return this->get_tx_gain(ALL_GAINS, chan); } + /*! + * Return the normalized TX gain value. + * + * See set_normalized_rx_gain() for a discussion of normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \returns The normalized gain (in [0, 1]) + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual double get_normalized_tx_gain(size_t chan = 0) = 0; + /*! * Get the TX gain range for the specified gain element. * For an empty name, calculate the overall gain range. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index e97787785..eab8c5283 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -831,6 +831,16 @@ public: } } + void set_normalized_rx_gain(double gain, size_t chan = 0) + { + if (gain > 1.0 || gain < 0.0) { + throw uhd::runtime_error("Normalized gain out of range, must be in [0, 1]."); + } + gain_range_t gain_range = get_rx_gain_range(ALL_GAINS, chan); + double abs_gain = (gain * (gain_range.stop() - gain_range.start())) + gain_range.start(); + set_rx_gain(abs_gain, ALL_GAINS, chan); + } + double get_rx_gain(const std::string &name, size_t chan){ try { return rx_gain_group(chan)->get_value(name); @@ -839,6 +849,21 @@ public: } } + double get_normalized_rx_gain(size_t chan) + { + gain_range_t gain_range = get_rx_gain_range(ALL_GAINS, chan); + double gain_range_width = gain_range.stop() - gain_range.start(); + // In case we have a device without a range of gains: + if (gain_range_width == 0.0) { + return 0; + } + double norm_gain = (get_rx_gain(ALL_GAINS, chan) - gain_range.start()) / gain_range_width; + // Avoid rounding errors: + if (norm_gain > 1.0) return 1.0; + if (norm_gain < 0.0) return 0.0; + return norm_gain; + } + gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ try { return rx_gain_group(chan)->get_range(name); @@ -1032,6 +1057,17 @@ public: } } + void set_normalized_tx_gain(double gain, size_t chan = 0) + { + if (gain > 1.0 || gain < 0.0) { + throw uhd::runtime_error("Normalized gain out of range, must be in [0, 1]."); + } + gain_range_t gain_range = get_tx_gain_range(ALL_GAINS, chan); + double abs_gain = (gain * (gain_range.stop() - gain_range.start())) + gain_range.start(); + set_tx_gain(abs_gain, ALL_GAINS, chan); + } + + double get_tx_gain(const std::string &name, size_t chan){ try { return tx_gain_group(chan)->get_value(name); @@ -1040,6 +1076,21 @@ public: } } + double get_normalized_tx_gain(size_t chan) + { + gain_range_t gain_range = get_tx_gain_range(ALL_GAINS, chan); + double gain_range_width = gain_range.stop() - gain_range.start(); + // In case we have a device without a range of gains: + if (gain_range_width == 0.0) { + return 0.0; + } + double norm_gain = (get_rx_gain(ALL_GAINS, chan) - gain_range.start()) / gain_range_width; + // Avoid rounding errors: + if (norm_gain > 1.0) return 1.0; + if (norm_gain < 0.0) return 0.0; + return norm_gain; + } + gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ try { return tx_gain_group(chan)->get_range(name); -- cgit v1.2.3 From 06bdef36dd5cfafe0d4c72a1d12488cd5599fca1 Mon Sep 17 00:00:00 2001 From: michael-west Date: Wed, 11 Feb 2015 16:32:27 -0800 Subject: UBX: Serialize SPI transactions --- host/lib/usrp/dboard/db_ubx.cpp | 58 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/dboard/db_ubx.cpp b/host/lib/usrp/dboard/db_ubx.cpp index dd30cf534..45817f599 100644 --- a/host/lib/usrp/dboard/db_ubx.cpp +++ b/host/lib/usrp/dboard/db_ubx.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include using namespace uhd; @@ -691,7 +692,7 @@ static const ubx_gpio_field_info_t ubx_v1_gpio_info[] = { }; /*********************************************************************** - * Macros and helper functions for routing and writing SPI registers + * Macros for routing and writing SPI registers **********************************************************************/ #define ROUTE_SPI(iface, dest) \ iface->set_gpio_out(dboard_iface::UNIT_TX, dest, 0x7); @@ -699,19 +700,6 @@ static const ubx_gpio_field_info_t ubx_v1_gpio_info[] = { #define WRITE_SPI(iface, val) \ iface->write_spi(dboard_iface::UNIT_TX, spi_config_t::EDGE_RISE, val, 32); -UHD_INLINE void write_spi_reg(dboard_iface::sptr iface, spi_dest_t dest, boost::uint32_t value) -{ - ROUTE_SPI(iface, dest); - WRITE_SPI(iface, value); -} - -UHD_INLINE void write_spi_regs(dboard_iface::sptr iface, spi_dest_t dest, std::vector values) -{ - ROUTE_SPI(iface, dest); - for (size_t i = 0; i < values.size(); i++) - WRITE_SPI(iface, values[i]); -} - /*********************************************************************** * UBX Class Definition **********************************************************************/ @@ -813,17 +801,17 @@ public: // Initialize LOs if (_rev == 0) { - _txlo1.reset(new max2870(boost::bind(&write_spi_regs, _iface, TXLO1, _1))); - _txlo2.reset(new max2870(boost::bind(&write_spi_regs, _iface, TXLO2, _1))); - _rxlo1.reset(new max2870(boost::bind(&write_spi_regs, _iface, RXLO1, _1))); - _rxlo2.reset(new max2870(boost::bind(&write_spi_regs, _iface, RXLO2, _1))); + _txlo1.reset(new max2870(boost::bind(&ubx_xcvr::write_spi_regs, this, TXLO1, _1))); + _txlo2.reset(new max2870(boost::bind(&ubx_xcvr::write_spi_regs, this, TXLO2, _1))); + _rxlo1.reset(new max2870(boost::bind(&ubx_xcvr::write_spi_regs, this, RXLO1, _1))); + _rxlo2.reset(new max2870(boost::bind(&ubx_xcvr::write_spi_regs, this, RXLO2, _1))); } else if (_rev == 1) { - _txlo1.reset(new max2871(boost::bind(&write_spi_regs, _iface, TXLO1, _1))); - _txlo2.reset(new max2871(boost::bind(&write_spi_regs, _iface, TXLO2, _1))); - _rxlo1.reset(new max2871(boost::bind(&write_spi_regs, _iface, RXLO1, _1))); - _rxlo2.reset(new max2871(boost::bind(&write_spi_regs, _iface, RXLO2, _1))); + _txlo1.reset(new max2871(boost::bind(&ubx_xcvr::write_spi_regs, this, TXLO1, _1))); + _txlo2.reset(new max2871(boost::bind(&ubx_xcvr::write_spi_regs, this, TXLO2, _1))); + _rxlo1.reset(new max2871(boost::bind(&ubx_xcvr::write_spi_regs, this, RXLO1, _1))); + _rxlo2.reset(new max2871(boost::bind(&ubx_xcvr::write_spi_regs, this, RXLO2, _1))); } else { @@ -918,10 +906,10 @@ public: ~ubx_xcvr(void) { // Shutdown synthesizers - _txlo1->shutdown(); - _txlo2->shutdown(); - _rxlo1->shutdown(); - _rxlo2->shutdown(); + _txlo1.reset(); + _txlo2.reset(); + _rxlo1.reset(); + _rxlo2.reset(); // Reset CPLD values _cpld_reg.value = 0; @@ -948,6 +936,21 @@ private: /*********************************************************************** * Helper Functions **********************************************************************/ + void write_spi_reg(spi_dest_t dest, boost::uint32_t value) + { + boost::mutex::scoped_lock lock(_spi_lock); + ROUTE_SPI(_iface, dest); + WRITE_SPI(_iface, value); + } + + void write_spi_regs(spi_dest_t dest, std::vector values) + { + boost::mutex::scoped_lock lock(_spi_lock); + ROUTE_SPI(_iface, dest); + BOOST_FOREACH(boost::uint32_t value, values) + WRITE_SPI(_iface, value); + } + void set_cpld_field(ubx_cpld_field_id_t id, boost::uint32_t value) { _cpld_reg.set_field(id, value); @@ -955,7 +958,7 @@ private: void write_cpld_reg() { - write_spi_reg(_iface, CPLD, _cpld_reg.value); + write_spi_reg(CPLD, _cpld_reg.value); } void set_gpio_field(ubx_gpio_field_id_t id, boost::uint32_t value) @@ -1389,6 +1392,7 @@ private: * Variables **********************************************************************/ dboard_iface::sptr _iface; + boost::mutex _spi_lock; ubx_cpld_reg_t _cpld_reg; boost::shared_ptr _txlo1; boost::shared_ptr _txlo2; -- cgit v1.2.3 From 956bf82d2800c346afe057e8c1ecf230900ee356 Mon Sep 17 00:00:00 2001 From: michael-west Date: Fri, 13 Feb 2015 17:49:48 -0800 Subject: UBX: Revert LO shutdown method in ubx_xcvr destructor --- host/lib/usrp/dboard/db_ubx.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/dboard/db_ubx.cpp b/host/lib/usrp/dboard/db_ubx.cpp index 45817f599..b6cc1421c 100644 --- a/host/lib/usrp/dboard/db_ubx.cpp +++ b/host/lib/usrp/dboard/db_ubx.cpp @@ -906,10 +906,10 @@ public: ~ubx_xcvr(void) { // Shutdown synthesizers - _txlo1.reset(); - _txlo2.reset(); - _rxlo1.reset(); - _rxlo2.reset(); + _txlo1->shutdown(); + _txlo2->shutdown(); + _rxlo1->shutdown(); + _rxlo2->shutdown(); // Reset CPLD values _cpld_reg.value = 0; -- cgit v1.2.3 From 8ec775e936b15404b34d34fd08cc5b3b3489055b Mon Sep 17 00:00:00 2001 From: Nicholas Corgan Date: Fri, 13 Feb 2015 08:40:50 -0800 Subject: usrp2: fixed image compatibility error message * Point to usrp2_card_burner_gui.py instead of usrp2_card_burner.py --- host/lib/usrp/usrp2/usrp2_iface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp2/usrp2_iface.cpp b/host/lib/usrp/usrp2/usrp2_iface.cpp index 65cf90a17..2f2c345be 100644 --- a/host/lib/usrp/usrp2/usrp2_iface.cpp +++ b/host/lib/usrp/usrp2/usrp2_iface.cpp @@ -387,7 +387,7 @@ public: //create the burner commands if (this->get_rev() == USRP2_REV3 or this->get_rev() == USRP2_REV4){ - const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner.py").string(); + const std::string card_burner = (fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "usrp2_card_burner_gui.py").string(); const std::string card_burner_cmd = str(boost::format("\"%s%s\" %s--fpga=\"%s\" %s--fw=\"%s\"") % sudo % card_burner % ml % fpga_image_path % ml % fw_image_path); return str(boost::format("%s\n%s") % print_utility_error("uhd_images_downloader.py") % card_burner_cmd); } -- cgit v1.2.3 From acfac7385c6130df54c60aa5c31bee6d06fa3f6a Mon Sep 17 00:00:00 2001 From: Ian Buckley Date: Mon, 9 Feb 2015 14:17:31 -0800 Subject: b200: Revised configuration of AD9361 for master_clock_rates >56e6MHz. Issues #649 & #691 --- host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index d3e53c80f..7268aff2d 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1049,7 +1049,7 @@ double ad9361_device_t::_tune_bbvco(const double rate) const double vcomin = 672e6; double vcorate; int vcodiv; - + /* Iterate over VCO dividers until appropriate divider is found. */ int i = 1; for (; i <= 6; i++) { @@ -1306,7 +1306,7 @@ double ad9361_device_t::_setup_rates(const double rate) divfactor = 16; _tfir_factor = 2; _rfir_factor = 2; - } else if ((rate >= 41e6) && (rate <= 56e6)) { + } else if ((rate >= 41e6) && (rate <= 58e6)) { // RX1 + RX2 enabled, 3, 1, 2, 2 _regs.rxfilt = B8(11100110); @@ -1316,15 +1316,15 @@ double ad9361_device_t::_setup_rates(const double rate) divfactor = 12; _tfir_factor = 2; _rfir_factor = 2; - } else if ((rate > 56e6) && (rate <= 61.44e6)) { - // RX1 + RX2 enabled, 3, 1, 1, 2 - _regs.rxfilt = B8(11100010); + } else if ((rate > 58e6) && (rate <= 61.44e6)) { + // RX1 + RX2 enabled, 2, 1, 2, 2 + _regs.rxfilt = B8(11010110); - // TX1 + TX2 enabled, 3, 1, 1, 1 - _regs.txfilt = B8(11100001); + // TX1 + TX2 enabled, 2, 1, 1, 2 + _regs.txfilt = B8(11010010); - divfactor = 6; - _tfir_factor = 1; + divfactor = 8; + _tfir_factor = 2; _rfir_factor = 2; } else { // should never get in here @@ -1340,7 +1340,7 @@ double ad9361_device_t::_setup_rates(const double rate) /* The DAC clock must be <= 336e6, and is either the ADC clock or 1/2 the * ADC clock.*/ if (adcclk > 336e6) { - /* Make the DAC clock = ADC/2, and bypass the TXFIR. */ + /* Make the DAC clock = ADC/2 */ _regs.bbpll = _regs.bbpll | 0x08; dacclk = adcclk / 2.0; } else { -- cgit v1.2.3 From ef00232f60777e0beab71cc749948e8389e3de84 Mon Sep 17 00:00:00 2001 From: Marcus Müller Date: Mon, 16 Feb 2015 19:16:22 +0100 Subject: b200: removed CMakeLists copy&paste B100 remains --- host/lib/usrp/b200/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/CMakeLists.txt b/host/lib/usrp/b200/CMakeLists.txt index a08c4bd03..ce89b5d80 100644 --- a/host/lib/usrp/b200/CMakeLists.txt +++ b/host/lib/usrp/b200/CMakeLists.txt @@ -20,7 +20,7 @@ ######################################################################## ######################################################################## -# Conditionally configure the B100 support +# Conditionally configure the B200 support ######################################################################## LIBUHD_REGISTER_COMPONENT("B200" ENABLE_B200 ON "ENABLE_LIBUHD;ENABLE_USB" OFF) -- cgit v1.2.3 From 4602ea9148e5e36fefca6402b7dcc5a1104e7410 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Fri, 20 Feb 2015 10:49:53 -0800 Subject: uhd: iq imbalance correction api --- host/include/uhd/usrp/multi_usrp.hpp | 8 ++++++++ host/lib/usrp/multi_usrp.cpp | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'host/lib') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index cebfda5a2..8357b9ffb 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -651,6 +651,14 @@ public: */ virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /*! + * Enable/disable the automatic IQ imbalance correction. + * + * \param enb true to enable automatic IQ balance correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_iq_balance(const bool enb, size_t chan) = 0; + /*! * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index eab8c5283..e7d39b244 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -916,6 +916,9 @@ public: if (chan != ALL_CHANS){ if (_tree->exists(rx_fe_root(chan) / "dc_offset" / "enable")) { _tree->access(rx_fe_root(chan) / "dc_offset" / "enable").set(enb); + } else if (_tree->exists(rx_rf_fe_root(chan) / "dc_offset" / "enable")) { + /*For B2xx devices the dc-offset correction is implemented in the rf front-end*/ + _tree->access(rx_rf_fe_root(chan) / "dc_offset" / "enable").set(enb); } else { UHD_MSG(warning) << "Setting DC offset compensation is not possible on this device." << std::endl; } @@ -940,6 +943,20 @@ public: } } + void set_rx_iq_balance(const bool enb, size_t chan){ + if (chan != ALL_CHANS){ + if (_tree->exists(rx_rf_fe_root(chan) / "iq_balance" / "enable")) { + _tree->access(rx_rf_fe_root(chan) / "iq_balance" / "enable").set(enb); + } else { + UHD_MSG(warning) << "Setting IQ imbalance compensation is not possible on this device." << std::endl; + } + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_iq_balance(enb, c); + } + } + void set_rx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ if (_tree->exists(rx_fe_root(chan) / "iq_balance" / "value")) { -- cgit v1.2.3 From 2b06c3815551c99d7691a7aa3dbcf6eaedc9e998 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Fri, 20 Feb 2015 10:51:45 -0800 Subject: b2xx: dc offset and iq imbalance correction control --- host/lib/usrp/b200/b200_impl.cpp | 14 +- host/lib/usrp/common/ad9361_ctrl.cpp | 28 ++++ host/lib/usrp/common/ad9361_ctrl.hpp | 15 +- .../usrp/common/ad9361_driver/ad9361_device.cpp | 125 +++++++++++++--- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 9 ++ .../usrp/common/ad9361_driver/ad9361_gain_tables.h | 162 ++++++++++----------- 6 files changed, 245 insertions(+), 108 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index c1729ead3..ada25ad59 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -591,7 +591,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr) b200_impl::~b200_impl(void) { - UHD_SAFE_CALL + UHD_SAFE_CALL ( _async_task.reset(); ) @@ -702,7 +702,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create(rf_fe_path / "use_lo_offset").set(false); _tree->create(rf_fe_path / "bandwidth" / "value") .coerce(boost::bind(&ad9361_ctrl::set_bw_filter, _codec_ctrl, key, _1)) - .set(40e6); + .set(56e6); _tree->create(rf_fe_path / "bandwidth" / "range") .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key)); _tree->create(rf_fe_path / "freq" / "value") @@ -715,6 +715,16 @@ void b200_impl::setup_radio(const size_t dspno) .publish(boost::bind(&ad9361_ctrl::get_temperature, _codec_ctrl)); //setup RX related stuff + if(direction) + { + _tree->create(rf_fe_path / "dc_offset" / "enable" ) + .subscribe(boost::bind(&ad9361_ctrl::set_dc_offset_auto, _codec_ctrl, key, _1)).set(true); + + _tree->create(rf_fe_path / "iq_balance" / "enable" ) + .subscribe(boost::bind(&ad9361_ctrl::set_iq_balance_auto, _codec_ctrl, key, _1)).set(true); + } + + //setup antenna stuff if (key[0] == 'R') { static const std::vector ants = boost::assign::list_of("TX/RX")("RX2"); diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index 3db6739e7..4a3c17cf1 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -178,6 +178,34 @@ public: return sensor_value_t("temp", _device.get_average_temperature(), "C"); } + void set_dc_offset_auto(const std::string &which, const bool on) + { + boost::lock_guard lock(_mutex); + + ad9361_device_t::direction_t direction = _get_direction_from_antenna(which); + _device.set_dc_offset_auto(direction,on); + } + + void set_dc_offset(const std::string &which, const std::complex value) + { + //This feature should not be used according to Analog Devices + throw uhd::runtime_error("ad9361_ctrl::set_dc_offset this feature is not supported on this device."); + } + + void set_iq_balance_auto(const std::string &which, const bool on) + { + boost::lock_guard lock(_mutex); + + ad9361_device_t::direction_t direction = _get_direction_from_antenna(which); + _device.set_iq_balance_auto(direction,on); + } + + void set_iq_balance(const std::string &which, const std::complex value) + { + //This feature should not be used according to Analog Devices + throw uhd::runtime_error("ad9361_ctrl::set_iq_balance this feature is not supported on this device."); + } + private: static ad9361_device_t::direction_t _get_direction_from_antenna(const std::string& antenna) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index f831f870d..94eee608e 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace uhd { namespace usrp { @@ -95,7 +96,19 @@ public: //! tune the given frontend, return the exact value virtual double tune(const std::string &which, const double value) = 0; - //! turn on/off data port loopback + //! set the DC offset for I and Q manually + virtual void set_dc_offset(const std::string &which, const std::complex value) = 0; + + //! enable or disable the BB/RF DC tracking feature + virtual void set_dc_offset_auto(const std::string &which, const bool on) = 0; + + //! set the IQ correction value manually + virtual void set_iq_balance(const std::string &which, const std::complex value) = 0; + + //! enable or disable the quadrature calibration + virtual void set_iq_balance_auto(const std::string &which, const bool on) = 0; + + //! turn on/off Catalina's data port loopback virtual void data_port_loopback(const bool on) = 0; //! read internal RSSI sensor diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index f1a82d71c..e5938184c 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -650,11 +651,12 @@ void ad9361_device_t::_setup_adc() } /* Calibrate the baseband DC offset. - * - * Note that this function is called from within the TX quadrature - * calibration function! */ + * Disables tracking + */ void ad9361_device_t::_calibrate_baseband_dc_offset() { + _io_iface->poke8(0x18b, 0x83); //Reset RF DC tracking flag + _io_iface->poke8(0x193, 0x3f); // Calibration settings _io_iface->poke8(0x190, 0x0f); // Set tracking coefficient //write_ad9361_reg(device, 0x190, /*0x0f*//*0xDF*/0x80*1 | 0x40*1 | (16+8/*+4*/)); // Set tracking coefficient: don't *4 counter, do decim /4, increased gain shift @@ -674,9 +676,8 @@ void ad9361_device_t::_calibrate_baseband_dc_offset() } /* Calibrate the RF DC offset. - * - * Note that this function is called from within the TX quadrature - * calibration function. */ + * Disables tracking + */ void ad9361_device_t::_calibrate_rf_dc_offset() { /* Some settings are frequency-dependent. */ @@ -691,7 +692,7 @@ void ad9361_device_t::_calibrate_rf_dc_offset() } _io_iface->poke8(0x185, 0x20); // RF DC Offset wait count - _io_iface->poke8(0x18b, 0x83); + _io_iface->poke8(0x18b, 0x83); // Disable tracking _io_iface->poke8(0x189, 0x30); /* Run the calibration! */ @@ -707,6 +708,16 @@ void ad9361_device_t::_calibrate_rf_dc_offset() } } +void ad9361_device_t::_configure_bb_rf_dc_tracking(const bool on) +{ + if(on) + { + _io_iface->poke8(0x18b, 0xad); // Enable BB and RF DC tracking + } else { + _io_iface->poke8(0x18b, 0x83); // Disable BB and RF DC tracking + } +} + /* Start the RX quadrature calibration. * * Note that we are using AD9361's 'tracking' feature for RX quadrature @@ -719,16 +730,20 @@ void ad9361_device_t::_calibrate_rx_quadrature() _io_iface->poke8(0x16e, 0x25); // RX Gain index to use for cal _io_iface->poke8(0x16a, 0x75); // Set Kexp phase _io_iface->poke8(0x16b, 0x15); // Set Kexp amplitude - _io_iface->poke8(0x169, 0xcf); // Continuous tracking mode - _io_iface->poke8(0x18b, 0xad); + + if(_use_iq_balance_correction) + { + _io_iface->poke8(0x169, 0xcf); // Continuous tracking mode. Gets disabled in _tx_quadrature_cal_routine! + } } -/* TX quadtrature calibration routine. +/* TX quadrature calibration routine. * * The TX quadrature needs to be done twice, once for each TX chain, with * only one register change in between. Thus, this function enacts the * calibrations, and it is called from calibrate_tx_quadrature. */ void ad9361_device_t::_tx_quadrature_cal_routine() { + /* This is a weird process, but here is how it works: * 1) Read the calibrated NCO frequency bits out of 0A3. * 2) Write the two bits to the RX NCO freq part of 0A0. @@ -773,12 +788,6 @@ void ad9361_device_t::_tx_quadrature_cal_routine() { _io_iface->poke8(0x0a4, 0xf0); // Cal setting conut _io_iface->poke8(0x0ae, 0x00); // Cal LPF gain index (split mode) - /* First, calibrate the baseband DC offset. */ - _calibrate_baseband_dc_offset(); - - /* Second, calibrate the RF DC offset. */ - _calibrate_rf_dc_offset(); - /* Now, calibrate the TX quadrature! */ size_t count = 0; _io_iface->poke8(0x016, 0x10); @@ -793,9 +802,7 @@ void ad9361_device_t::_tx_quadrature_cal_routine() { } /* Run the TX quadrature calibration. - * - * Note that from within this function we are also triggering the baseband - * and RF DC calibrations. */ + */ void ad9361_device_t::_calibrate_tx_quadrature() { /* Make sure we are, in fact, in the ALERT state. If not, something is @@ -879,7 +886,7 @@ void ad9361_device_t::_program_mixer_gm_subtable() void ad9361_device_t::_program_gain_table() { /* Figure out which gain table we should be using for our current * frequency band. */ - boost::uint8_t (*gain_table)[5] = NULL; + boost::uint8_t (*gain_table)[3] = NULL; boost::uint8_t new_gain_table; if (_rx_freq < 1300e6) { gain_table = gain_table_sub_1300mhz; @@ -910,9 +917,9 @@ void ad9361_device_t::_program_gain_table() { boost::uint8_t index = 0; for (; index < 77; index++) { _io_iface->poke8(0x130, index); - _io_iface->poke8(0x131, gain_table[index][1]); - _io_iface->poke8(0x132, gain_table[index][2]); - _io_iface->poke8(0x133, gain_table[index][3]); + _io_iface->poke8(0x131, gain_table[index][0]); + _io_iface->poke8(0x132, gain_table[index][1]); + _io_iface->poke8(0x133, gain_table[index][2]); _io_iface->poke8(0x137, 0x1E); _io_iface->poke8(0x134, 0x00); _io_iface->poke8(0x134, 0x00); @@ -1256,6 +1263,7 @@ double ad9361_device_t::_setup_rates(const double rate) int divfactor = 0; _tfir_factor = 0; _rfir_factor = 0; + if (rate < 0.33e6) { // RX1 + RX2 enabled, 3, 2, 2, 4 _regs.rxfilt = B8(11101111); @@ -1411,6 +1419,8 @@ void ad9361_device_t::initialize() _rx2_gain = 0; _tx1_gain = 0; _tx2_gain = 0; + _use_dc_offset_correction = true; + _use_iq_balance_correction = true; /* Reset the device. */ _io_iface->poke8(0x000, 0x01); @@ -1563,8 +1573,11 @@ void ad9361_device_t::initialize() _setup_adc(); + _calibrate_baseband_dc_offset(); + _calibrate_rf_dc_offset(); _calibrate_tx_quadrature(); _calibrate_rx_quadrature(); + _configure_bb_rf_dc_tracking(_use_dc_offset_correction); // cals done, set PPORT config switch (_client_params->get_digital_interface_mode()) { @@ -1687,8 +1700,11 @@ double ad9361_device_t::set_clock_rate(const double req_rate) _setup_adc(); + _calibrate_baseband_dc_offset(); + _calibrate_rf_dc_offset(); _calibrate_tx_quadrature(); _calibrate_rx_quadrature(); + _configure_bb_rf_dc_tracking(_use_dc_offset_correction); // cals done, set PPORT config switch (_client_params->get_digital_interface_mode()) { @@ -1841,9 +1857,11 @@ double ad9361_device_t::tune(direction_t direction, const double value) _reprogram_gains(); /* Run the calibration algorithms. */ + _calibrate_baseband_dc_offset(); + _calibrate_rf_dc_offset(); _calibrate_tx_quadrature(); _calibrate_rx_quadrature(); - + _configure_bb_rf_dc_tracking(_use_dc_offset_correction); //if this is not done here, bb dc offset is not good /* If we were in the FDD state, return it now. */ if (not_in_alert) { _io_iface->poke8(0x014, 0x21); @@ -1990,4 +2008,63 @@ double ad9361_device_t::get_average_temperature(const double cal_offset, const s return d_temp; } +void ad9361_device_t::set_dc_offset_auto(direction_t direction, const bool on) +{ + if(direction == RX) + { + _use_dc_offset_correction = on; + _configure_bb_rf_dc_tracking(_use_dc_offset_correction); + if(on) + { + _io_iface->poke8(0x182, (_io_iface->peek8(0x182) & (~((1 << 7) | (1 << 6) | (1 << 3) | (1 << 2))))); //Clear force bits + //Do a single shot DC offset cal before enabling tracking (Not possible if not in ALERT state. Is it necessary?) + } else { + //clear current config values + _io_iface->poke8(0x182, (_io_iface->peek8(0x182) | ((1 << 7) | (1 << 6) | (1 << 3) | (1 << 2)))); //Set input A and input B&C force enable bits + _io_iface->poke8(0x174, 0x00); + _io_iface->poke8(0x175, 0x00); + _io_iface->poke8(0x176, 0x00); + _io_iface->poke8(0x177, 0x00); + _io_iface->poke8(0x178, 0x00); + _io_iface->poke8(0x17D, 0x00); + _io_iface->poke8(0x17E, 0x00); + _io_iface->poke8(0x17F, 0x00); + _io_iface->poke8(0x180, 0x00); + _io_iface->poke8(0x181, 0x00); + } + } else { + // DC offset is removed during TX quad cal + throw uhd::runtime_error("[ad9361_device_t] [set_iq_balance_auto] INVALID_CODE_PATH"); + } +} + +void ad9361_device_t::set_iq_balance_auto(direction_t direction, const bool on) +{ + if(direction == RX) + { + _use_iq_balance_correction = on; + if(on) + { + //disable force registers and enable tracking + _io_iface->poke8(0x182, (_io_iface->peek8(0x182) & (~ ( (1<<1) | (1<<0) | (1<<5) | (1<<4) )))); + _calibrate_rx_quadrature(); + } else { + //disable IQ tracking + _io_iface->poke8(0x169, 0xc0); + //clear current config values + _io_iface->poke8(0x182, (_io_iface->peek8(0x182) | ((1 << 1) | (1 << 0) | (1 << 5) | (1 << 4)))); //Set Rx2 input B&C force enable bit + _io_iface->poke8(0x17B, 0x00); + _io_iface->poke8(0x17C, 0x00); + _io_iface->poke8(0x179, 0x00); + _io_iface->poke8(0x17A, 0x00); + _io_iface->poke8(0x170, 0x00); + _io_iface->poke8(0x171, 0x00); + _io_iface->poke8(0x172, 0x00); + _io_iface->poke8(0x173, 0x00); + } + } else { + throw uhd::runtime_error("[ad9361_device_t] [set_iq_balance_auto] INVALID_CODE_PATH"); + } +} + }} diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 8f64922f8..93dc413d5 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -72,6 +72,12 @@ public: */ double get_average_temperature(const double cal_offset = -30.0, const size_t num_samples = 3); + /* Turn on/off AD9361's RX DC offset correction */ + void set_dc_offset_auto(direction_t direction, const bool on); + + /* Turn on/off AD9361's RX IQ imbalance correction */ + void set_iq_balance_auto(direction_t direction, const bool on); + //Constants static const double AD9361_MAX_GAIN; static const double AD9361_MAX_CLOCK_RATE; @@ -102,6 +108,7 @@ private: //Methods double _tune_helper(direction_t direction, const double value); double _setup_rates(const double rate); double _get_temperature(const double cal_offset, const double timeout = 0.1); + void _configure_bb_rf_dc_tracking(const bool on); private: //Members typedef struct { @@ -130,6 +137,8 @@ private: //Members chip_regs_t _regs; //Synchronization boost::recursive_mutex _mutex; + bool _use_dc_offset_correction; + bool _use_iq_balance_correction; }; }} //namespace diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h b/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h index 786029d6e..553655fa5 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h @@ -7,91 +7,91 @@ #include -boost::uint8_t gain_table_sub_1300mhz[77][5] = { {0,0x00,0x00,0x20,1}, - {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0}, - {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0}, - {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0}, - {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0}, - {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0}, - {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0}, - {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0}, - {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0}, - {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0}, - {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x27,0x20,1}, - {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0}, - {34,0x04,0x2B,0x00,1}, {35,0x24,0x21,0x20,0}, {36,0x24,0x22,0x00,1}, - {37,0x44,0x20,0x20,0}, {38,0x44,0x21,0x00,0}, {39,0x44,0x22,0x00,0}, - {40,0x44,0x23,0x00,0}, {41,0x44,0x24,0x00,0}, {42,0x44,0x25,0x00,0}, - {43,0x44,0x26,0x00,0}, {44,0x44,0x27,0x00,0}, {45,0x44,0x28,0x00,0}, - {46,0x44,0x29,0x00,0}, {47,0x44,0x2A,0x00,0}, {48,0x44,0x2B,0x00,0}, - {49,0x44,0x2C,0x00,0}, {50,0x44,0x2D,0x00,0}, {51,0x44,0x2E,0x00,0}, - {52,0x44,0x2F,0x00,0}, {53,0x44,0x30,0x00,0}, {54,0x44,0x31,0x00,0}, - {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, - {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, - {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, - {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, - {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, - {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, - {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, - {76,0x6F,0x38,0x20,1}}; +boost::uint8_t gain_table_sub_1300mhz[77][3] = { +{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x00 }, { 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 }, +{ 0x00, 0x04, 0x00 }, { 0x00, 0x05, 0x00 }, { 0x01, 0x03, 0x20 }, +{ 0x01, 0x04, 0x00 }, { 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 }, +{ 0x01, 0x07, 0x00 }, { 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 }, +{ 0x01, 0x0A, 0x00 }, { 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 }, +{ 0x01, 0x0D, 0x00 }, { 0x01, 0x0E, 0x00 }, { 0x02, 0x09, 0x20 }, +{ 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x00 }, { 0x02, 0x0C, 0x00 }, +{ 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 }, { 0x02, 0x0F, 0x00 }, +{ 0x02, 0x10, 0x00 }, { 0x02, 0x2B, 0x20 }, { 0x02, 0x2C, 0x00 }, +{ 0x04, 0x28, 0x20 }, { 0x04, 0x29, 0x00 }, { 0x04, 0x2A, 0x00 }, +{ 0x04, 0x2B, 0x00 }, { 0x24, 0x20, 0x20 }, { 0x24, 0x21, 0x00 }, +{ 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 }, { 0x44, 0x22, 0x00 }, +{ 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 }, { 0x44, 0x25, 0x00 }, +{ 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 }, { 0x44, 0x28, 0x00 }, +{ 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 }, { 0x44, 0x2B, 0x00 }, +{ 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 }, { 0x44, 0x2E, 0x00 }, +{ 0x44, 0x2F, 0x00 }, { 0x44, 0x30, 0x00 }, { 0x44, 0x31, 0x00 }, +{ 0x44, 0x32, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 }, +{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 }, +{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 }, +{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 }, +{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 }, +{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 }, +{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 }, +{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } }; -boost::uint8_t gain_table_1300mhz_to_4000mhz[77][5] = { {0,0x00,0x00,0x20,1}, - {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0}, - {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0}, - {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0}, - {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0}, - {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0}, - {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0}, - {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0}, - {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0}, - {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0}, - {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x28,0x20,1}, - {31,0x04,0x29,0x00,0}, {32,0x04,0x2A,0x00,0}, {33,0x04,0x2B,0x00,0}, - {34,0x24,0x20,0x20,0}, {35,0x24,0x21,0x00,1}, {36,0x44,0x20,0x20,0}, - {37,0x44,0x21,0x00,1}, {38,0x44,0x22,0x00,0}, {39,0x44,0x23,0x00,0}, - {40,0x44,0x24,0x00,0}, {41,0x44,0x25,0x00,0}, {42,0x44,0x26,0x00,0}, - {43,0x44,0x27,0x00,0}, {44,0x44,0x28,0x00,0}, {45,0x44,0x29,0x00,0}, - {46,0x44,0x2A,0x00,0}, {47,0x44,0x2B,0x00,0}, {48,0x44,0x2C,0x00,0}, - {49,0x44,0x2D,0x00,0}, {50,0x44,0x2E,0x00,0}, {51,0x44,0x2F,0x00,0}, - {52,0x44,0x30,0x00,0}, {53,0x44,0x31,0x00,0}, {54,0x44,0x32,0x00,0}, - {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, - {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, - {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, - {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, - {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, - {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, - {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, - {76,0x6F,0x38,0x20,1}}; +boost::uint8_t gain_table_1300mhz_to_4000mhz[77][3] = { +{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x00 }, { 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 }, +{ 0x00, 0x04, 0x00 }, { 0x00, 0x05, 0x00 }, { 0x01, 0x03, 0x20 }, +{ 0x01, 0x04, 0x00 }, { 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 }, +{ 0x01, 0x07, 0x00 }, { 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 }, +{ 0x01, 0x0A, 0x00 }, { 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 }, +{ 0x01, 0x0D, 0x00 }, { 0x01, 0x0E, 0x00 }, { 0x02, 0x09, 0x20 }, +{ 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x00 }, { 0x02, 0x0C, 0x00 }, +{ 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 }, { 0x02, 0x0F, 0x00 }, +{ 0x02, 0x10, 0x00 }, { 0x02, 0x2B, 0x20 }, { 0x02, 0x2C, 0x00 }, +{ 0x04, 0x27, 0x20 }, { 0x04, 0x28, 0x00 }, { 0x04, 0x29, 0x00 }, +{ 0x04, 0x2A, 0x00 }, { 0x04, 0x2B, 0x00 }, { 0x24, 0x21, 0x20 }, +{ 0x24, 0x22, 0x00 }, { 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 }, +{ 0x44, 0x22, 0x00 }, { 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 }, +{ 0x44, 0x25, 0x00 }, { 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 }, +{ 0x44, 0x28, 0x00 }, { 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 }, +{ 0x44, 0x2B, 0x00 }, { 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 }, +{ 0x44, 0x2E, 0x00 }, { 0x44, 0x2F, 0x00 }, { 0x44, 0x30, 0x00 }, +{ 0x44, 0x31, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 }, +{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 }, +{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 }, +{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 }, +{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 }, +{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 }, +{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 }, +{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } }; -boost::uint8_t gain_table_4000mhz_to_6000mhz[77][5] = { {0,0x00,0x00,0x20,1}, - {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x00,0x00,0}, - {4,0x00,0x00,0x00,0}, {5,0x00,0x01,0x00,0}, {6,0x00,0x02,0x00,0}, - {7,0x00,0x03,0x00,0}, {8,0x01,0x01,0x20,1}, {9,0x01,0x02,0x00,0}, - {10,0x01,0x03,0x00,0}, {11,0x01,0x04,0x20,1}, {12,0x01,0x05,0x00,0}, - {13,0x01,0x06,0x00,0}, {14,0x01,0x07,0x00,0}, {15,0x01,0x08,0x00,0}, - {16,0x01,0x09,0x00,0}, {17,0x01,0x0A,0x00,0}, {18,0x01,0x0B,0x00,0}, - {19,0x01,0x0C,0x00,0}, {20,0x02,0x08,0x20,1}, {21,0x02,0x09,0x00,0}, - {22,0x02,0x0A,0x00,0}, {23,0x02,0x0B,0x20,1}, {24,0x02,0x0C,0x00,0}, - {25,0x02,0x0D,0x00,0}, {26,0x02,0x0E,0x00,0}, {27,0x02,0x0F,0x00,0}, - {28,0x02,0x2A,0x20,1}, {29,0x02,0x2B,0x00,0}, {30,0x04,0x27,0x20,1}, - {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0}, - {34,0x04,0x2B,0x00,0}, {35,0x04,0x2C,0x00,0}, {36,0x04,0x2D,0x00,0}, - {37,0x24,0x20,0x20,1}, {38,0x24,0x21,0x00,0}, {39,0x24,0x22,0x00,0}, - {40,0x44,0x20,0x20,1}, {41,0x44,0x21,0x00,0}, {42,0x44,0x22,0x00,0}, - {43,0x44,0x23,0x00,0}, {44,0x44,0x24,0x00,0}, {45,0x44,0x25,0x00,0}, - {46,0x44,0x26,0x00,0}, {47,0x44,0x27,0x00,0}, {48,0x44,0x28,0x00,0}, - {49,0x44,0x29,0x00,0}, {50,0x44,0x2A,0x00,0}, {51,0x44,0x2B,0x00,0}, - {52,0x44,0x2C,0x00,0}, {53,0x44,0x2D,0x00,0}, {54,0x44,0x2E,0x00,0}, - {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0}, - {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0}, - {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0}, - {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1}, - {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1}, - {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1}, - {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1}, - {76,0x6F,0x38,0x20,1}}; +boost::uint8_t gain_table_4000mhz_to_6000mhz[77][3] = { +{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, +{ 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x00 }, +{ 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 }, { 0x01, 0x01, 0x20 }, +{ 0x01, 0x02, 0x00 }, { 0x01, 0x03, 0x00 }, { 0x01, 0x04, 0x20 }, +{ 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 }, { 0x01, 0x07, 0x00 }, +{ 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 }, { 0x01, 0x0A, 0x00 }, +{ 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 }, { 0x02, 0x08, 0x20 }, +{ 0x02, 0x09, 0x00 }, { 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x20 }, +{ 0x02, 0x0C, 0x00 }, { 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 }, +{ 0x02, 0x0F, 0x00 }, { 0x02, 0x2A, 0x20 }, { 0x02, 0x2B, 0x00 }, +{ 0x04, 0x27, 0x20 }, { 0x04, 0x28, 0x00 }, { 0x04, 0x29, 0x00 }, +{ 0x04, 0x2A, 0x00 }, { 0x04, 0x2B, 0x00 }, { 0x04, 0x2C, 0x00 }, +{ 0x04, 0x2D, 0x00 }, { 0x24, 0x20, 0x20 }, { 0x24, 0x21, 0x00 }, +{ 0x24, 0x22, 0x00 }, { 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 }, +{ 0x44, 0x22, 0x00 }, { 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 }, +{ 0x44, 0x25, 0x00 }, { 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 }, +{ 0x44, 0x28, 0x00 }, { 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 }, +{ 0x44, 0x2B, 0x00 }, { 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 }, +{ 0x44, 0x2E, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 }, +{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 }, +{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 }, +{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 }, +{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 }, +{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 }, +{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 }, +{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } }; #endif /* INCLUDED_AD9361_GAIN_TABLES_HPP */ -- cgit v1.2.3 From 566dbc2b5d0751167c9d868743dbebfff4d22afe Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Mon, 23 Feb 2015 17:08:21 -0800 Subject: e3xx: support for dc offset and iq balance control --- host/lib/usrp/common/ad9361_ctrl.cpp | 13 ------------- host/lib/usrp/common/ad9361_ctrl.hpp | 13 +++++++++++-- host/lib/usrp/e300/e300_network.cpp | 6 ++++++ host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 28 +++++++++++++++++++++++++++ host/lib/usrp/e300/e300_remote_codec_ctrl.hpp | 4 ++++ 5 files changed, 49 insertions(+), 15 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index 4a3c17cf1..ada74cda5 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -16,7 +16,6 @@ // #include "ad9361_ctrl.hpp" -#include #include #include #include @@ -186,12 +185,6 @@ public: _device.set_dc_offset_auto(direction,on); } - void set_dc_offset(const std::string &which, const std::complex value) - { - //This feature should not be used according to Analog Devices - throw uhd::runtime_error("ad9361_ctrl::set_dc_offset this feature is not supported on this device."); - } - void set_iq_balance_auto(const std::string &which, const bool on) { boost::lock_guard lock(_mutex); @@ -200,12 +193,6 @@ public: _device.set_iq_balance_auto(direction,on); } - void set_iq_balance(const std::string &which, const std::complex value) - { - //This feature should not be used according to Analog Devices - throw uhd::runtime_error("ad9361_ctrl::set_iq_balance this feature is not supported on this device."); - } - private: static ad9361_device_t::direction_t _get_direction_from_antenna(const std::string& antenna) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index 94eee608e..5396de225 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -97,13 +98,21 @@ public: virtual double tune(const std::string &which, const double value) = 0; //! set the DC offset for I and Q manually - virtual void set_dc_offset(const std::string &which, const std::complex value) = 0; + void set_dc_offset(const std::string &, const std::complex) + { + //This feature should not be used according to Analog Devices + throw uhd::runtime_error("ad9361_ctrl::set_dc_offset this feature is not supported on this device."); + } //! enable or disable the BB/RF DC tracking feature virtual void set_dc_offset_auto(const std::string &which, const bool on) = 0; //! set the IQ correction value manually - virtual void set_iq_balance(const std::string &which, const std::complex value) = 0; + void set_iq_balance(const std::string &, const std::complex) + { + //This feature should not be used according to Analog Devices + throw uhd::runtime_error("ad9361_ctrl::set_iq_balance this feature is not supported on this device."); + } //! enable or disable the quadrature calibration virtual void set_iq_balance_auto(const std::string &which, const bool on) = 0; diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 7ed83c6c6..3396931e3 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -229,6 +229,12 @@ static void e300_codec_ctrl_tunnel( 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); + break; default: UHD_MSG(status) << "Got unknown request?!" << std::endl; //Zero out actions to fail this request on client diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index 0ea837a85..15222a96a 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -130,6 +130,34 @@ public: 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(transaction_t::ACTION_SET_DC_OFFSET_AUTO); + if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); + else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); + else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); + else if (which == "RX2") _args.which = uhd::htonx(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(transaction_t::ACTION_SET_IQ_BALANCE_AUTO); + if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); + else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); + else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); + else if (which == "RX2") _args.which = uhd::htonx(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(); + } + private: void _transact() { { diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp index d92e9bd58..855ab0f42 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp @@ -35,6 +35,8 @@ public: double freq; double rssi; double temp; + boost::uint32_t use_dc_correction; + boost::uint32_t use_iq_correction; boost::uint64_t bits; }; @@ -46,6 +48,8 @@ public: static const boost::uint32_t ACTION_SET_LOOPBACK = 14; static const boost::uint32_t ACTION_GET_RSSI = 15; static const boost::uint32_t ACTION_GET_TEMPERATURE = 16; + static const boost::uint32_t ACTION_SET_DC_OFFSET_AUTO = 17; + static const boost::uint32_t ACTION_SET_IQ_BALANCE_AUTO = 18; //Values for "which" static const boost::uint32_t CHAIN_NONE = 0; -- cgit v1.2.3 From 78be3d548be78ffd871a0563499a6df0bfdf14b4 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 23 Feb 2015 13:30:17 -0800 Subject: e300: fc: This should fix the RX flow control. Two issues: - Call the correct overflow handler e300_impl vs rx_vita - Don't lie about buffer sizes and window sizes Signed-off-by: Moritz Fischer --- host/lib/usrp/e300/e300_impl.hpp | 1 + host/lib/usrp/e300/e300_io_impl.cpp | 40 ++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp index a4170ee42..59e0d59ce 100644 --- a/host/lib/usrp/e300/e300_impl.hpp +++ b/host/lib/usrp/e300/e300_impl.hpp @@ -70,6 +70,7 @@ 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 = 32; // per flow ctrl window // crossbar settings static const boost::uint8_t E300_RADIO_DEST_PREFIX_TX = 0; diff --git a/host/lib/usrp/e300/e300_io_impl.cpp b/host/lib/usrp/e300/e300_io_impl.cpp index dcb6f2afe..a1d0a8da1 100644 --- a/host/lib/usrp/e300/e300_io_impl.cpp +++ b/host/lib/usrp/e300/e300_io_impl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -226,6 +227,18 @@ void e300_impl::_handle_overflow( } } +static size_t get_rx_flow_control_window(size_t frame_size, size_t sw_buff_size, double fullness_factor) +{ + if (fullness_factor < 0.01 || fullness_factor > 1) { + throw uhd::value_error("recv_buff_fullness must be between 0.01 and 1 inclusive (1% to 100%)"); + } + + size_t window_in_pkts = (static_cast(sw_buff_size * fullness_factor) / frame_size); + if (window_in_pkts == 0) { + throw uhd::value_error("recv_buff_size must be larger than the recv_frame_size."); + } + return window_in_pkts; +} static void handle_rx_flowctrl( const boost::uint32_t sid, @@ -457,25 +470,38 @@ rx_streamer::sptr e300_impl::get_rx_stream(const uhd::stream_args_t &args_) id.num_outputs = 1; my_streamer->set_converter(id); + perif.framer->clear(); perif.framer->set_nsamps_per_packet(spp); //seems to be a good place to set this perif.framer->set_sid((data_sid << 16) | (data_sid >> 16)); perif.framer->setup(args); perif.ddc->setup(args); + + // flow control setup + const size_t frame_size = data_xports.recv->get_recv_frame_size(); + const size_t num_frames = data_xports.recv->get_num_recv_frames(); + const size_t fc_window = get_rx_flow_control_window( + frame_size,num_frames * frame_size, + E300_RX_SW_BUFF_FULLNESS); + const size_t fc_handle_window = std::max(1, fc_window / E300_RX_FC_REQUEST_FREQ); + + UHD_LOG << "RX Flow Control Window = " << fc_window + << ", RX Flow Control Handler Window = " + << fc_handle_window << std::endl; + + perif.framer->configure_flow_control(fc_window); + boost::shared_ptr fc_cache(new e300_rx_fc_cache_t()); + my_streamer->set_xport_chan_get_buff(stream_i, boost::bind( &zero_copy_if::get_recv_buff, data_xports.recv, _1 ), true /*flush*/); my_streamer->set_overflow_handler(stream_i, - boost::bind(&rx_vita_core_3000::handle_overflow, perif.framer) + boost::bind(&e300_impl::_handle_overflow, this, boost::ref(perif), + boost::weak_ptr(my_streamer)) ); - //setup flow control - const size_t fc_window = data_xports.recv->get_num_recv_frames(); - perif.framer->configure_flow_control(fc_window); - boost::shared_ptr fc_cache(new e300_rx_fc_cache_t()); my_streamer->set_xport_handle_flowctrl(stream_i, boost::bind(&handle_rx_flowctrl, data_sid, data_xports.send, fc_cache, _1), - static_cast(static_cast(fc_window) * E300_RX_SW_BUFF_FULLNESS), - true/*init*/); + fc_handle_window, true/*init*/); my_streamer->set_issue_stream_cmd(stream_i, boost::bind(&rx_vita_core_3000::issue_stream_command, perif.framer, _1) -- cgit v1.2.3 From 963dcaa6a75862aec9ee4924dd88fa0901b39934 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Mon, 23 Feb 2015 14:12:59 -0800 Subject: e300: fc: Clean up the TX flowcontrol setup a bit. Use named constant instant of magic constant for response frequency. Signed-off-by: Moritz Fischer --- host/lib/usrp/e300/e300_impl.hpp | 1 + host/lib/usrp/e300/e300_io_impl.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp index 59e0d59ce..c7d683f58 100644 --- a/host/lib/usrp/e300/e300_impl.hpp +++ b/host/lib/usrp/e300/e300_impl.hpp @@ -71,6 +71,7 @@ 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 = 32; // per flow ctrl window +static const size_t E300_TX_FC_RESPONSE_FREQ = 8; // per flow ctrl window // crossbar settings static const boost::uint8_t E300_RADIO_DEST_PREFIX_TX = 0; diff --git a/host/lib/usrp/e300/e300_io_impl.cpp b/host/lib/usrp/e300/e300_io_impl.cpp index a1d0a8da1..fa4915ed1 100644 --- a/host/lib/usrp/e300/e300_io_impl.cpp +++ b/host/lib/usrp/e300/e300_io_impl.cpp @@ -590,7 +590,13 @@ tx_streamer::sptr e300_impl::get_tx_stream(const uhd::stream_args_t &args_) //flow control setup const size_t fc_window = data_xports.send->get_num_send_frames(); - perif.deframer->configure_flow_control(0/*cycs off*/, fc_window/8/*pkts*/); + const size_t fc_handle_window = std::max(1, fc_window/E300_TX_FC_RESPONSE_FREQ); + + UHD_LOG << "TX Flow Control Window = " << fc_window + << ", TX Flow Control Handler Window = " + << fc_handle_window << std::endl; + + perif.deframer->configure_flow_control(0/*cycs off*/, fc_handle_window/*pkts*/); boost::shared_ptr fc_cache(new e300_tx_fc_cache_t()); fc_cache->stream_channel = stream_i; fc_cache->device_channel = args.channels[stream_i]; -- cgit v1.2.3 From 499bcc0238315a2e1f01625d725a67b168acb99f Mon Sep 17 00:00:00 2001 From: Marcus Müller Date: Fri, 27 Feb 2015 19:44:26 +0100 Subject: uhd: Fixed: Exception during detection kills device::make On systems with libusb but not USB, device detection for USB devices fails (lsusb itself dies with "error -99"). This crashes the device detection process itself. Also made the documentation for ::make match what it actually does. --- host/include/uhd/device.hpp | 4 +++- host/lib/device.cpp | 23 ++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 1e88a4138..5ca48f8e9 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -77,7 +77,9 @@ public: /*! * \brief Create a new device from the device address hint. * - * The make routine will call find and pick one of the results. + * The method will go through the registered device types and pick one of + * the discovered devices. + * * By default, the first result will be used to create a new device. * Use the which parameter as an index into the list of results. * diff --git a/host/lib/device.cpp b/host/lib/device.cpp index 006ea6ec8..3e84d5bea 100644 --- a/host/lib/device.cpp +++ b/host/lib/device.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011,2014 Ettus Research LLC +// Copyright 2010-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 @@ -90,9 +90,9 @@ device_addrs_t device::find(const device_addr_t &hint, device_filter_t filter){ device_addrs_t device_addrs; - BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){ - try{ - if(filter == ANY or fcn.get<2>() == filter){ + BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()) { + try { + if (filter == ANY or fcn.get<2>() == filter) { device_addrs_t discovered_addrs = fcn.get<0>()(hint); device_addrs.insert( device_addrs.begin(), @@ -101,7 +101,7 @@ device_addrs_t device::find(const device_addr_t &hint, device_filter_t filter){ ); } } - catch(const std::exception &e){ + catch (const std::exception &e) { UHD_MSG(error) << "Device discovery error: " << e.what() << std::endl; } } @@ -119,12 +119,17 @@ device::sptr device::make(const device_addr_t &hint, device_filter_t filter, siz std::vector dev_addr_makers; BOOST_FOREACH(const dev_fcn_reg_t &fcn, get_dev_fcn_regs()){ - if(filter == ANY or fcn.get<2>() == filter){ - BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){ - //append the discovered address and its factory function - dev_addr_makers.push_back(dev_addr_make_t(dev_addr, fcn.get<1>())); + try{ + if(filter == ANY or fcn.get<2>() == filter){ + BOOST_FOREACH(device_addr_t dev_addr, fcn.get<0>()(hint)){ + //append the discovered address and its factory function + dev_addr_makers.push_back(dev_addr_make_t(dev_addr, fcn.get<1>())); + } } } + catch(const std::exception &e){ + UHD_MSG(error) << "Device discovery error: " << e.what() << std::endl; + } } //check that we found any devices -- cgit v1.2.3 From bcd364df0fadf28c2b8bd7933939a7a099d6da04 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Thu, 26 Feb 2015 13:07:44 +0100 Subject: N2x0: Fixed missing usage of send_buff_size --- host/lib/usrp/usrp2/io_impl.cpp | 3 ++- host/lib/usrp/usrp2/usrp2_impl.cpp | 5 +++-- host/lib/usrp/usrp2/usrp2_impl.hpp | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 9ee6abed0..81be97fa5 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -239,7 +239,8 @@ void usrp2_impl::io_init(void){ //init the tx xport and flow control monitor _io_impl->tx_xports.push_back(_mbc[mb].tx_dsp_xport); _io_impl->fc_mons.push_back(flow_control_monitor::sptr(new flow_control_monitor( - USRP2_SRAM_BYTES/_mbc[mb].tx_dsp_xport->get_send_frame_size() + device_addr.cast("send_buff_size", USRP2_SRAM_BYTES) / + _mbc[mb].tx_dsp_xport->get_send_frame_size() ))); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 16e8a1f22..50b8431a1 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -316,9 +316,10 @@ static zero_copy_if::sptr make_xport( /*********************************************************************** * Structors **********************************************************************/ -usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ +usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) : + device_addr(_device_addr) +{ UHD_MSG(status) << "Opening a USRP2/N-Series device..." << std::endl; - device_addr_t device_addr = _device_addr; //setup the dsp transport hints (default to a large recv buff) if (not device_addr.has_key("recv_buff_size")){ diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index edbb7888b..fac4b3907 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -116,6 +116,7 @@ private: bool _ignore_cal_file; //io impl methods and members + uhd::device_addr_t device_addr; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); void update_tick_rate(const double rate); -- cgit v1.2.3 From 99ab759233c85de000d16ad0f10660819e9456f1 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Thu, 5 Mar 2015 11:14:55 -0800 Subject: e300: added missing break --- host/lib/usrp/e300/e300_network.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 3396931e3..693e78b6e 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -226,6 +226,7 @@ static void e300_codec_ctrl_tunnel( 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; -- cgit v1.2.3 From be14725245cca756e19c48d84aedc54064e8706c Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Thu, 5 Mar 2015 15:25:13 -0800 Subject: b2xx: AGC support --- host/lib/usrp/b200/b200_impl.cpp | 10 ++ host/lib/usrp/common/ad9361_ctrl.cpp | 21 +++ host/lib/usrp/common/ad9361_ctrl.hpp | 6 + .../usrp/common/ad9361_driver/ad9361_device.cpp | 170 ++++++++++++++++++--- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 12 +- 5 files changed, 195 insertions(+), 24 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index ada25ad59..663696926 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -734,6 +734,16 @@ void b200_impl::setup_radio(const size_t dspno) .set("RX2"); _tree->create(rf_fe_path / "sensors" / "rssi") .publish(boost::bind(&ad9361_ctrl::get_rssi, _codec_ctrl, key)); + + //AGC setup + const std::list mode_strings = boost::assign::list_of("slow")("fast"); + _tree->create(rf_fe_path / "gain" / "agc" / "enable") + .subscribe(boost::bind((&ad9361_ctrl::set_agc), _codec_ctrl, key, _1)) + .set(false); + _tree->create(rf_fe_path / "gain" / "agc" / "mode" / "value") + .subscribe(boost::bind((&ad9361_ctrl::set_agc_mode), _codec_ctrl, key, _1)).set(mode_strings.front()); + _tree->create >(rf_fe_path / "gain" / "agc" / "mode" / "options") + .set(mode_strings); } if (key[0] == 'T') { diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index ada74cda5..a0a5fa663 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -107,6 +107,27 @@ public: return _device.set_gain(direction, chain, value); } + void set_agc(const std::string &which, bool enable) + { + boost::lock_guard lock(_mutex); + + ad9361_device_t::chain_t chain =_get_chain_from_antenna(which); + _device.set_agc(chain, enable); + } + + void set_agc_mode(const std::string &which, const std::string &mode) + { + boost::lock_guard lock(_mutex); + ad9361_device_t::chain_t chain =_get_chain_from_antenna(which); + if(mode == "slow") { + _device.set_agc_mode(chain, ad9361_device_t::GAIN_MODE_SLOW_AGC); + } else if (mode == "fast"){ + _device.set_agc_mode(chain, ad9361_device_t::GAIN_MODE_FAST_AGC); + } else { + throw uhd::runtime_error("ad9361_ctrl got an invalid AGC option."); + } + } + //! set a new clock rate, return the exact value double set_clock_rate(const double rate) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index 5396de225..0dd1b08d9 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -88,6 +88,12 @@ public: //! set the gain for a particular gain element virtual double set_gain(const std::string &which, const double value) = 0; + //! Enable or disable the AGC module + virtual void set_agc(const std::string &which, bool enable) = 0; + + //! configure the AGC module to slow or fast mode + virtual void set_agc_mode(const std::string &which, const std::string &mode) = 0; + //! set a new clock rate, return the exact value virtual double set_clock_rate(const double rate) = 0; diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index e5938184c..ba66769dd 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -945,28 +945,58 @@ void ad9361_device_t::_program_gain_table() { /* Setup gain control registers. * - * This really only needs to be done once, at initialization. */ -void ad9361_device_t::_setup_gain_control() + * This really only needs to be done once, at initialization. + * If AGC is used the mode select bits (Reg 0x0FA) must be written manually */ +void ad9361_device_t::_setup_gain_control(bool agc) { - _io_iface->poke8(0x0FA, 0xE0); // Gain Control Mode Select - _io_iface->poke8(0x0FB, 0x08); // Table, Digital Gain, Man Gain Ctrl - _io_iface->poke8(0x0FC, 0x23); // Incr Step Size, ADC Overrange Size - _io_iface->poke8(0x0FD, 0x4C); // Max Full/LMT Gain Table Index - _io_iface->poke8(0x0FE, 0x44); // Decr Step Size, Peak Overload Time - _io_iface->poke8(0x100, 0x6F); // Max Digital Gain - _io_iface->poke8(0x104, 0x2F); // ADC Small Overload Threshold - _io_iface->poke8(0x105, 0x3A); // ADC Large Overload Threshold - _io_iface->poke8(0x107, 0x31); // Large LMT Overload Threshold - _io_iface->poke8(0x108, 0x39); // Small LMT Overload Threshold - _io_iface->poke8(0x109, 0x23); // Rx1 Full/LMT Gain Index - _io_iface->poke8(0x10A, 0x58); // Rx1 LPF Gain Index - _io_iface->poke8(0x10B, 0x00); // Rx1 Digital Gain Index - _io_iface->poke8(0x10C, 0x23); // Rx2 Full/LMT Gain Index - _io_iface->poke8(0x10D, 0x18); // Rx2 LPF Gain Index - _io_iface->poke8(0x10E, 0x00); // Rx2 Digital Gain Index - _io_iface->poke8(0x114, 0x30); // Low Power Threshold - _io_iface->poke8(0x11A, 0x27); // Initial LMT Gain Limit - _io_iface->poke8(0x081, 0x00); // Tx Symbol Gain Control + /* The AGC mode configuration should be good for all cases. + * However, non AGC configuration still used for backward compatibility. */ + if (agc) { + /*mode select bits must be written before hand!*/ + _io_iface->poke8(0x0FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + _io_iface->poke8(0x0FC, 0x23); // Incr Step Size, ADC Overrange Size + _io_iface->poke8(0x0FD, 0x4C); // Max Full/LMT Gain Table Index + _io_iface->poke8(0x0FE, 0x44); // Decr Step Size, Peak Overload Time + _io_iface->poke8(0x100, 0x6F); // Max Digital Gain + _io_iface->poke8(0x101, 0x0A); // Max Digital Gain + _io_iface->poke8(0x103, 0x08); // Max Digital Gain + _io_iface->poke8(0x104, 0x2F); // ADC Small Overload Threshold + _io_iface->poke8(0x105, 0x3A); // ADC Large Overload Threshold + _io_iface->poke8(0x106, 0x22); // Max Digital Gain + _io_iface->poke8(0x107, 0x2B); // Large LMT Overload Threshold + _io_iface->poke8(0x108, 0x31); + _io_iface->poke8(0x111, 0x0A); + _io_iface->poke8(0x11A, 0x1C); + _io_iface->poke8(0x120, 0x0C); + _io_iface->poke8(0x121, 0x44); + _io_iface->poke8(0x122, 0x44); + _io_iface->poke8(0x123, 0x11); + _io_iface->poke8(0x124, 0xF5); + _io_iface->poke8(0x125, 0x3B); + _io_iface->poke8(0x128, 0x03); + _io_iface->poke8(0x129, 0x56); + _io_iface->poke8(0x12A, 0x22); + } else { + _io_iface->poke8(0x0FA, 0xE0); // Gain Control Mode Select + _io_iface->poke8(0x0FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + _io_iface->poke8(0x0FC, 0x23); // Incr Step Size, ADC Overrange Size + _io_iface->poke8(0x0FD, 0x4C); // Max Full/LMT Gain Table Index + _io_iface->poke8(0x0FE, 0x44); // Decr Step Size, Peak Overload Time + _io_iface->poke8(0x100, 0x6F); // Max Digital Gain + _io_iface->poke8(0x104, 0x2F); // ADC Small Overload Threshold + _io_iface->poke8(0x105, 0x3A); // ADC Large Overload Threshold + _io_iface->poke8(0x107, 0x31); // Large LMT Overload Threshold + _io_iface->poke8(0x108, 0x39); // Small LMT Overload Threshold + _io_iface->poke8(0x109, 0x23); // Rx1 Full/LMT Gain Index + _io_iface->poke8(0x10A, 0x58); // Rx1 LPF Gain Index + _io_iface->poke8(0x10B, 0x00); // Rx1 Digital Gain Index + _io_iface->poke8(0x10C, 0x23); // Rx2 Full/LMT Gain Index + _io_iface->poke8(0x10D, 0x18); // Rx2 LPF Gain Index + _io_iface->poke8(0x10E, 0x00); // Rx2 Digital Gain Index + _io_iface->poke8(0x114, 0x30); // Low Power Threshold + _io_iface->poke8(0x11A, 0x27); // Initial LMT Gain Limit + _io_iface->poke8(0x081, 0x00); // Tx Symbol Gain Control + } } /* Setup the RX or TX synthesizers. @@ -1421,6 +1451,10 @@ void ad9361_device_t::initialize() _tx2_gain = 0; _use_dc_offset_correction = true; _use_iq_balance_correction = true; + _rx1_agc_mode = GAIN_MODE_SLOW_AGC; + _rx2_agc_mode = GAIN_MODE_SLOW_AGC; + _rx1_agc_enable = false; + _rx2_agc_enable = false; /* Reset the device. */ _io_iface->poke8(0x000, 0x01); @@ -1564,7 +1598,7 @@ void ad9361_device_t::initialize() _program_mixer_gm_subtable(); _program_gain_table(); - _setup_gain_control(); + _setup_gain_control(false); _calibrate_baseband_rx_analog_filter(); _calibrate_baseband_tx_analog_filter(); @@ -1690,7 +1724,7 @@ double ad9361_device_t::set_clock_rate(const double req_rate) _program_mixer_gm_subtable(); _program_gain_table(); - _setup_gain_control(); + _setup_gain_control(false); _reprogram_gains(); _calibrate_baseband_rx_analog_filter(); @@ -2067,4 +2101,94 @@ void ad9361_device_t::set_iq_balance_auto(direction_t direction, const bool on) } } +/* Sets the RX gain mode to be used. + * If a transition from an AGC to an non AGC mode occurs (or vice versa) + * the gain configuration will be reloaded. */ +void ad9361_device_t::_setup_agc(chain_t chain, gain_mode_t gain_mode) +{ + boost::uint8_t gain_mode_reg = 0; + boost::uint8_t gain_mode_prev = 0; + boost::uint8_t gain_mode_bits_pos = 0; + + gain_mode_reg = _io_iface->peek8(0x0FA); + gain_mode_prev = (gain_mode_reg & 0x0F); + + if (chain == CHAIN_1) { + gain_mode_bits_pos = 0; + } else if (chain == CHAIN_2) { + gain_mode_bits_pos = 2; + } else + { + throw uhd::runtime_error("[ad9361_device_t] Wrong value for chain"); + } + + gain_mode_reg = (gain_mode_reg & (~(0x03<poke8(0x0FA, gain_mode_reg); + boost::uint8_t gain_mode_status = _io_iface->peek8(0x0FA); + gain_mode_status = (gain_mode_status & 0x0F); + /*Check if gain mode configuration needs to be reprogrammed*/ + if (((gain_mode_prev == 0) && (gain_mode_status != 0)) || ((gain_mode_prev != 0) && (gain_mode_status == 0))) { + if (gain_mode_status == 0) { + /*load manual mode config*/ + _setup_gain_control(false); + } else { + /*load agc mode config*/ + _setup_gain_control(true); + } + } +} + +void ad9361_device_t::set_agc(chain_t chain, bool enable) +{ + if(chain == CHAIN_1) { + _rx1_agc_enable = enable; + if(enable) { + _setup_agc(chain, _rx1_agc_mode); + } else { + _setup_agc(chain, GAIN_MODE_MANUAL); + } + } else if (chain == CHAIN_2){ + _rx2_agc_enable = enable; + if(enable) { + _setup_agc(chain, _rx2_agc_mode); + } else { + _setup_agc(chain, GAIN_MODE_MANUAL); + } + } else + { + throw uhd::runtime_error("[ad9361_device_t] Wrong value for chain"); + } +} + +void ad9361_device_t::set_agc_mode(chain_t chain, gain_mode_t gain_mode) +{ + if(chain == CHAIN_1) { + _rx1_agc_mode = gain_mode; + if(_rx1_agc_enable) { + _setup_agc(chain, _rx1_agc_mode); + } + } else if(chain == CHAIN_2){ + _rx2_agc_mode = gain_mode; + if(_rx2_agc_enable) { + _setup_agc(chain, _rx2_agc_mode); + } + } else + { + throw uhd::runtime_error("[ad9361_device_t] Wrong value for chain"); + } +} + }} diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 93dc413d5..1cfff9971 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -16,6 +16,7 @@ class ad9361_device_t : public boost::noncopyable public: enum direction_t { RX, TX }; enum chain_t { CHAIN_1, CHAIN_2 }; + enum gain_mode_t {GAIN_MODE_MANUAL, GAIN_MODE_SLOW_AGC, GAIN_MODE_FAST_AGC}; ad9361_device_t(ad9361_params::sptr client, ad9361_io::sptr io_iface) : _client_params(client), _io_iface(io_iface) {} @@ -78,6 +79,12 @@ public: /* Turn on/off AD9361's RX IQ imbalance correction */ void set_iq_balance_auto(direction_t direction, const bool on); + /* Configure AD9361's AGC module to use either fast or slow AGC mode. */ + void set_agc_mode(chain_t chain, gain_mode_t gain_mode); + + /* Enable AD9361's AGC gain mode. */ + void set_agc(chain_t chain, bool enable); + //Constants static const double AD9361_MAX_GAIN; static const double AD9361_MAX_CLOCK_RATE; @@ -101,7 +108,7 @@ private: //Methods void _calibrate_tx_quadrature(); void _program_mixer_gm_subtable(); void _program_gain_table(); - void _setup_gain_control(); + void _setup_gain_control(bool use_agc); void _setup_synth(direction_t direction, double vcorate); double _tune_bbvco(const double rate); void _reprogram_gains(); @@ -109,6 +116,7 @@ private: //Methods double _setup_rates(const double rate); double _get_temperature(const double cal_offset, const double timeout = 0.1); void _configure_bb_rf_dc_tracking(const bool on); + void _setup_agc(chain_t chain, gain_mode_t gain_mode); private: //Members typedef struct { @@ -133,6 +141,8 @@ private: //Members double _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain; boost::int32_t _tfir_factor; boost::int32_t _rfir_factor; + gain_mode_t _rx1_agc_mode, _rx2_agc_mode; + bool _rx1_agc_enable, _rx2_agc_enable; //Register soft-copies chip_regs_t _regs; //Synchronization -- cgit v1.2.3 From b8815805372feef40b9254a320e091a40c65377e Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Thu, 5 Mar 2015 15:25:31 -0800 Subject: e3xx: AGC support --- host/lib/usrp/e300/e300_network.cpp | 9 ++++++ host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 40 +++++++++++++++++++++++++-- host/lib/usrp/e300/e300_remote_codec_ctrl.hpp | 4 +++ 3 files changed, 51 insertions(+), 2 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index 693e78b6e..cb06a5740 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -235,6 +235,15 @@ static void e300_codec_ctrl_tunnel( 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; default: UHD_MSG(status) << "Got unknown request?!" << std::endl; diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index 15222a96a..871885a7b 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -147,13 +147,49 @@ public: void set_iq_balance_auto(const std::string &which, const bool on) { _clear(); - _args.action = uhd::htonx(transaction_t::ACTION_SET_IQ_BALANCE_AUTO); + _args.action = uhd::htonx(transaction_t::ACTION_SET_IQ_BALANCE_AUTO); + if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); + else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); + else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); + else if (which == "RX2") _args.which = uhd::htonx(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(transaction_t::ACTION_SET_AGC); if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); else if (which == "RX2") _args.which = uhd::htonx(transaction_t::CHAIN_RX2); else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string."); - _args.use_iq_correction = on ? 1 : 0; + _args.use_agc = enable ? 1 : 0; + + _transact(); + } + + void set_agc_mode(const std::string &which, const std::string &mode) + { + _clear(); + _args.action = uhd::htonx(transaction_t::ACTION_SET_AGC_MODE); + + if (which == "TX1") _args.which = uhd::htonx(transaction_t::CHAIN_TX1); + else if (which == "TX2") _args.which = uhd::htonx(transaction_t::CHAIN_TX2); + else if (which == "RX1") _args.which = uhd::htonx(transaction_t::CHAIN_RX1); + else if (which == "RX2") _args.which = uhd::htonx(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(); } diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp index 855ab0f42..459d0ec55 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp @@ -37,6 +37,8 @@ public: double temp; boost::uint32_t use_dc_correction; boost::uint32_t use_iq_correction; + boost::uint32_t use_agc; + boost::uint32_t agc_mode; boost::uint64_t bits; }; @@ -50,6 +52,8 @@ public: static const boost::uint32_t ACTION_GET_TEMPERATURE = 16; static const boost::uint32_t ACTION_SET_DC_OFFSET_AUTO = 17; static const boost::uint32_t ACTION_SET_IQ_BALANCE_AUTO = 18; + static const boost::uint32_t ACTION_SET_AGC = 19; + static const boost::uint32_t ACTION_SET_AGC_MODE = 20; //Values for "which" static const boost::uint32_t CHAIN_NONE = 0; -- cgit v1.2.3 From 33edac343488fdd87337e308b277adca69f16819 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Thu, 5 Mar 2015 15:24:46 -0800 Subject: uhd: AGC support --- host/include/uhd/usrp/multi_usrp.hpp | 10 ++++++++++ host/lib/usrp/multi_usrp.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'host/lib') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 8357b9ffb..e8fcdb4b6 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -513,6 +513,16 @@ public: */ virtual void set_normalized_rx_gain(double gain, size_t chan = 0) = 0; + /*! + * Enable or disable the RX AGC module. + * Once this module is enabled manual gain settings will be ignored. + * The AGC will start in a default configuration which should be good for most use cases. + * Device specific configuration parameters can be found in the property tree. + * \param on Enable or Disable the AGC + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_agc(bool enable, size_t chan = 0) = 0; + /*! * Get the RX gain value for the specified gain element. * For an empty name, sum across all gain elements. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index e7d39b244..bc6e121d0 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -824,6 +824,26 @@ public: } void set_rx_gain(double gain, const std::string &name, size_t chan){ + /* Check if any AGC mode is enable and if so warn the user */ + if (chan != ALL_CHANS) { + if (_tree->exists(rx_rf_fe_root(chan) / "gain" / "agc")) { + bool agc = _tree->access(rx_rf_fe_root(chan) / "gain" / "agc" / "enable").get(); + if(agc) { + UHD_MSG(warning) << "AGC enabled for this channel. Setting will be ignored." << std::endl; + } + } + } else { + for (size_t c = 0; c < get_rx_num_channels(); c++){ + if (_tree->exists(rx_rf_fe_root(c) / "gain" / "agc")) { + bool agc = _tree->access(rx_rf_fe_root(chan) / "gain" / "agc" / "enable").get(); + if(agc) { + UHD_MSG(warning) << "AGC enabled for this channel. Setting will be ignored." << std::endl; + } + } + } + } + /* Apply gain setting. + * If device is in AGC mode it will ignore the setting. */ try { return rx_gain_group(chan)->set_value(gain, name); } catch (uhd::key_error &e) { @@ -841,6 +861,22 @@ public: set_rx_gain(abs_gain, ALL_GAINS, chan); } + void set_rx_agc(bool enable, size_t chan = 0) + { + if (chan != ALL_CHANS){ + if (_tree->exists(rx_rf_fe_root(chan) / "gain" / "agc" / "enable")) { + _tree->access(rx_rf_fe_root(chan) / "gain" / "agc" / "enable").set(enable); + } else { + UHD_MSG(warning) << "AGC is not available on this device." << std::endl; + } + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_agc(enable, c); + } + + } + double get_rx_gain(const std::string &name, size_t chan){ try { return rx_gain_group(chan)->get_value(name); -- cgit v1.2.3 From d9241b78d32402093c37ab7ce2f4336699219ed4 Mon Sep 17 00:00:00 2001 From: Ian Buckley Date: Mon, 9 Mar 2015 11:20:56 -0700 Subject: 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 --- host/examples/CMakeLists.txt | 2 +- host/examples/fpgpio.cpp | 418 ------------------------------ host/examples/gpio.cpp | 462 ++++++++++++++++++++++++++++++++++ host/lib/usrp/b200/b200_impl.cpp | 35 ++- host/lib/usrp/b200/b200_impl.hpp | 7 +- host/lib/usrp/b200/b200_regs.hpp | 2 + host/lib/usrp/cores/gpio_core_200.hpp | 9 +- host/lib/usrp/e300/e300_impl.cpp | 34 +-- host/lib/usrp/e300/e300_impl.hpp | 6 +- host/lib/usrp/x300/x300_impl.cpp | 35 +-- host/lib/usrp/x300/x300_impl.hpp | 6 +- 11 files changed, 555 insertions(+), 461 deletions(-) delete mode 100644 host/examples/fpgpio.cpp create mode 100644 host/examples/gpio.cpp (limited to 'host/lib') 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 . -// - -// 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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(&args)->default_value(""), "multi uhd device address args") - ("repeat", "repeat loop until Ctrl-C is pressed") - ("cpu", po::value(&cpu)->default_value(FPGPIO_DEFAULT_CPU_FORMAT), "cpu data format") - ("otw", po::value(&otw)->default_value(FPGPIO_DEFAULT_OTW_FORMAT), "over the wire data format") - ("rx_rate", po::value(&rx_rate)->default_value(FPGPIO_DEFAULT_RX_RATE), "rx sample rate") - ("tx_rate", po::value(&tx_rate)->default_value(FPGPIO_DEFAULT_TX_RATE), "tx sample rate") - ("dwell", po::value(&dwell)->default_value(FPGPIO_DEFAULT_DWELL_TIME), "dwell time in seconds for each test case") - ("gpio", po::value(&fpgpio)->default_value(FPGPIO_DEFAULT_GPIO), "name of gpio bank") - ("bits", po::value(&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 rx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu)); - std::vector tx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu)); - std::vector 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 . +// + +// 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" for TX daughter card GPIO, or +// "RX" 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 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(&args)->default_value(""), "multi uhd device address args") + ("repeat", "repeat loop until Ctrl-C is pressed") + ("cpu", po::value(&cpu)->default_value(GPIO_DEFAULT_CPU_FORMAT), "cpu data format") + ("otw", po::value(&otw)->default_value(GPIO_DEFAULT_OTW_FORMAT), "over the wire data format") + ("rx_rate", po::value(&rx_rate)->default_value(GPIO_DEFAULT_RX_RATE), "rx sample rate") + ("tx_rate", po::value(&tx_rate)->default_value(GPIO_DEFAULT_TX_RATE), "tx sample rate") + ("dwell", po::value(&dwell)->default_value(GPIO_DEFAULT_DWELL_TIME), "dwell time in seconds for each test case") + ("bank", po::value(&gpio)->default_value(GPIO_DEFAULT_GPIO), "name of gpio bank") + ("bits", po::value(&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(&ddr_str)->default_value(GPIO_DEFAULT_DDR), "GPIO DDR reg value") + ("out", po::value(&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 rx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu)); + std::vector tx_buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(cpu)); + std::vector 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 @@ -528,6 +528,19 @@ b200_impl::b200_impl(const device_addr_t &device_addr) static const std::vector clock_sources = boost::assign::list_of("internal")("external")("gpsdo"); _tree->create >(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(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(mb_path / "gpio" / "FP0" / "READBACK") + .publish(boost::bind(&b200_impl::get_fp_gpio, this, _radio_perifs[0].fp_gpio)); + //////////////////////////////////////////////////////////////////// // dboard eeproms but not really //////////////////////////////////////////////////////////////////// @@ -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 #include +#include #include #include #include #include +#include + +typedef enum{CTRL,DDR,OUT,ATR_0X,ATR_RX,ATR_TX,ATR_XX} gpio_attr_t; +typedef std::map 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 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(mb_path / "gpio" / "INT0" / attr) - .subscribe(boost::bind(&e300_impl::_set_internal_gpio, this, fp_gpio, attr, _1)) + _tree->create(mb_path / "gpio" / "INT0" / attr.second) + .subscribe(boost::bind(&e300_impl::_set_internal_gpio, this, fp_gpio, attr.first, _1)) .set(0); } _tree->create(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(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 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(mb_path / "gpio" / "FP0" / attr) + _tree->create(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(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 -- cgit v1.2.3 From 17b8f6cf6e6a0b812516ca0641cdac5425996fca Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Sat, 7 Mar 2015 11:04:58 -0500 Subject: e300: comment out unused variables in control::make when E300_NATIVE is not defined. --- host/lib/usrp/e300/e300_ublox_control_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_ublox_control_impl.cpp b/host/lib/usrp/e300/e300_ublox_control_impl.cpp index a0ec10271..0f56fdb67 100644 --- a/host/lib/usrp/e300/e300_ublox_control_impl.cpp +++ b/host/lib/usrp/e300/e300_ublox_control_impl.cpp @@ -498,7 +498,7 @@ control::sptr control::make(const std::string &node, const size_t baud_rate) #else using namespace uhd::usrp::gps::ublox::ubx; -control::sptr control::make(const std::string &node, const size_t baud_rate) +control::sptr control::make(const std::string& /* node */, const size_t /* baud_rate */) { throw uhd::assertion_error("control::sptr::make: !E300_NATIVE"); } -- cgit v1.2.3 From a55b5a097da01606f23209713bf1ce754be5b7d3 Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Fri, 30 Jan 2015 15:11:15 -0800 Subject: uhd: Introduced filter API. This is a unified API to access filters on USRP devices. Filters can be accessed through the property tree, or multi_usrp. --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/filters.hpp | 286 ++++++++++++++++++++++++++++++++++ host/include/uhd/usrp/multi_usrp.hpp | 33 ++++ host/lib/types/CMakeLists.txt | 1 + host/lib/types/filters.cpp | 74 +++++++++ host/lib/usrp/multi_usrp.cpp | 83 ++++++++++ 6 files changed, 478 insertions(+) create mode 100644 host/include/uhd/types/filters.hpp create mode 100644 host/lib/types/filters.cpp (limited to 'host/lib') diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index f5a92a805..b82c2b7f2 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -37,6 +37,7 @@ UHD_INSTALL(FILES tune_request.hpp tune_result.hpp wb_iface.hpp + filters.hpp DESTINATION ${INCLUDE_DIR}/uhd/types COMPONENT headers ) diff --git a/host/include/uhd/types/filters.hpp b/host/include/uhd/types/filters.hpp new file mode 100644 index 000000000..0cb23b294 --- /dev/null +++ b/host/include/uhd/types/filters.hpp @@ -0,0 +1,286 @@ +// +// Copyright 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 +// 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 . +// + +#ifndef INCLUDED_UHD_TYPES_FILTERS_HPP +#define INCLUDED_UHD_TYPES_FILTERS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ + + class UHD_API filter_info_base + { + public: + typedef boost::shared_ptr sptr; + enum filter_type + { + ANALOG_LOW_PASS, + ANALOG_BAND_PASS, + DIGITAL_I16, + DIGITAL_FIR_I16 + }; + + filter_info_base( + filter_type type, + bool bypass, + size_t position_index + ): + _type(type), _bypass(bypass), + _position_index(position_index) + { + //NOP + } + + inline virtual bool is_bypassed() + { + return _bypass; + } + + inline filter_type get_type() + { + return _type; + } + + virtual ~filter_info_base() + { + //NOP + } + + virtual std::string to_pp_string(); + + protected: + filter_type _type; + bool _bypass; + size_t _position_index; + + }; + + UHD_API std::ostream& operator<<(std::ostream& os, filter_info_base& f); + + class UHD_API analog_filter_base : public filter_info_base + { + std::string _analog_type; + public: + typedef boost::shared_ptr sptr; + analog_filter_base( + filter_type type, + bool bypass, + size_t position_index, + const std::string& analog_type + ): + filter_info_base(type, bypass, position_index), + _analog_type(analog_type) + { + //NOP + } + + inline const std::string& get_analog_type() + { + return _analog_type; + } + + virtual std::string to_pp_string(); + }; + + class UHD_API analog_filter_lp : public analog_filter_base + { + double _cutoff; + double _rolloff; + + public: + typedef boost::shared_ptr sptr; + analog_filter_lp( + filter_type type, + bool bypass, + size_t position_index, + const std::string& analog_type, + double cutoff, + double rolloff + ): + analog_filter_base(type, bypass, position_index, analog_type), + _cutoff(cutoff), + _rolloff(rolloff) + { + //NOP + } + + inline double get_cutoff() + { + return _cutoff; + } + + inline double get_rolloff() + { + return _cutoff; + } + + inline void set_cutoff(const double cutoff) + { + _cutoff = cutoff; + } + + virtual std::string to_pp_string(); + }; + + template + class UHD_API digital_filter_base : public filter_info_base + { + protected: + double _rate; + boost::uint32_t _interpolation; + boost::uint32_t _decimation; + tap_t _tap_full_scale; + boost::uint32_t _max_num_taps; + std::vector _taps; + + public: + typedef boost::shared_ptr sptr; + digital_filter_base( + filter_type type, + bool bypass, + size_t position_index, + double rate, + size_t interpolation, + size_t decimation, + double tap_full_scale, + size_t max_num_taps, + const std::vector& taps + ): + filter_info_base(type, bypass, position_index), + _rate(rate), + _interpolation(interpolation), + _decimation(decimation), + _tap_full_scale(tap_full_scale), + _max_num_taps(max_num_taps), + _taps(taps) + { + //NOP + } + + inline double get_output_rate() + { + return (_bypass ? _rate : (_rate / _decimation * _interpolation)); + } + + inline double get_input_rate() + { + return _rate; + } + + inline double get_interpolation() + { + return _interpolation; + } + + inline double get_decimation() + { + return _decimation; + } + + inline double get_tap_full_scale() + { + return _tap_full_scale; + } + + inline std::vector& get_taps() + { + return _taps; + } + + virtual std::string to_pp_string() + { + std::ostringstream os; + os< + class UHD_API digital_filter_fir : public digital_filter_base + { + public: + typedef boost::shared_ptr > sptr; + + digital_filter_fir( + filter_info_base::filter_type type, + bool bypass, size_t position_index, + double rate, + size_t interpolation, + size_t decimation, + size_t tap_bit_width, + size_t max_num_taps, + const std::vector& taps + ): + digital_filter_base(type, bypass, position_index, rate, interpolation, decimation, tap_bit_width, max_num_taps, taps) + { + //NOP + } + + void set_taps(const std::vector& taps) + { + std::size_t num_taps = taps.size(); + if(num_taps < this->_max_num_taps){ + UHD_MSG(warning) << "digital_filter_fir::set_taps not enough coefficients. Appending zeros"; + std::vector coeffs; + for (size_t i = 0; i < this->_max_num_taps; i++) + { + if(i < num_taps) + { + coeffs.push_back(taps[i]); + } else { + coeffs.push_back(0); + } + } + this->_taps = coeffs; + } else { + this->_taps = taps; + } + } + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_FILTERS_HPP */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index e8fcdb4b6..1c408d56e 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -973,6 +974,38 @@ public: */ virtual boost::uint32_t get_gpio_attr(const std::string &bank, const std::string &attr, const size_t mboard = 0) = 0; + /******************************************************************* + * Filter API methods + ******************************************************************/ + + /*! + * Enumerate the available filters in the signal path. + * \param search_mask + * \parblock + * Select only certain filter names by specifying this search mask. + * + * E.g. if search mask is set to "rx_frontends/A" only filter names including that string will be returned. + * \endparblock + * \return a vector of strings representing the selected filter names. + */ + virtual std::vector get_filter_names(const std::string &search_mask = "") = 0; + + /*! + * Return the filter object for the given name. + * \param path the name of the filter as returned from get_filter_names(). + * \return a filter_info_base::sptr. + */ + virtual filter_info_base::sptr get_filter(const std::string &path) = 0; + + /*! + * Write back a filter obtained by get_filter() to the signal path. + * This filter can be a modified version of the originally returned one. + * The information about Rx or Tx is contained in the path parameter. + * \param path the name of the filter as returned from get_filter_names(). + * \param filter the filter_info_base::sptr of the filter object to be written + */ + virtual void set_filter(const std::string &path, filter_info_base::sptr filter) = 0; + }; }} diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index 853da3fe2..821754386 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -91,4 +91,5 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/tune.cpp ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wb_iface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/filters.cpp ) diff --git a/host/lib/types/filters.cpp b/host/lib/types/filters.cpp new file mode 100644 index 000000000..4ee06491f --- /dev/null +++ b/host/lib/types/filters.cpp @@ -0,0 +1,74 @@ +// +// Copyright 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 +// 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 . +// + +#include + +using namespace uhd; + +std::ostream& uhd::operator<<(std::ostream& os, filter_info_base& f) +{ + return os << f.to_pp_string(); +} + +std::string filter_info_base::to_pp_string() +{ + std::ostringstream os; + os << "[filter_info_base]" << std::endl; + switch(_type){ + case ANALOG_LOW_PASS: + os << "type: " << "Analog Low-pass" << std::endl; + break; + case ANALOG_BAND_PASS: + os << "type: " << "Analog Band-pass" << std::endl; + break; + case DIGITAL_I16: + os << "type: " << "Digital (i16)" << std::endl; + break; + case DIGITAL_FIR_I16: + os << "type: " << "Digital FIR (i16)" << std::endl; + break; + default: + os << "type: " << "Unknown type!" << std::endl; + break; + } + + os << "bypass enable: " << _bypass << std::endl + <<"position index: " << _position_index << std::endl; + + std::string str = os.str(); + return str; +} + +std::string analog_filter_base::to_pp_string() +{ + std::ostringstream os; + os << filter_info_base::to_pp_string() << + "\t[analog_filter_base]" << std::endl << + "\tdesc: " << _analog_type << std::endl; + return std::string(os.str()); + +} + +std::string analog_filter_lp::to_pp_string() +{ + std::ostringstream os; + os << analog_filter_base::to_pp_string() << + "\t\t[analog_filter_lp]" << std::endl << + "\t\tcutoff: " << _cutoff << std::endl << + "\t\trolloff: " << _rolloff << std::endl; + return std::string(os.str()); +} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index bc6e121d0..570c67875 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include using namespace uhd; @@ -1007,6 +1009,87 @@ public: } } + std::vector get_filter_names(const std::string &search_mask) + { + std::vector ret; + + for (size_t chan = 0; chan < get_rx_num_channels(); chan++){ + + if (_tree->exists(rx_rf_fe_root(chan) / "filters")) { + std::vector names = _tree->list(rx_rf_fe_root(chan) / "filters"); + for(size_t i = 0; i < names.size(); i++) + { + std::string name = rx_rf_fe_root(chan) / "filters" / names[i]; + if((search_mask.empty()) or boost::contains(name, search_mask)) { + ret.push_back(name); + } + } + } + if (_tree->exists(rx_dsp_root(chan) / "filters")) { + std::vector names = _tree->list(rx_dsp_root(chan) / "filters"); + for(size_t i = 0; i < names.size(); i++) + { + std::string name = rx_dsp_root(chan) / "filters" / names[i]; + if((search_mask.empty()) or (boost::contains(name, search_mask))) { + ret.push_back(name); + } + } + } + + } + + for (size_t chan = 0; chan < get_tx_num_channels(); chan++){ + + if (_tree->exists(tx_rf_fe_root(chan) / "filters")) { + std::vector names = _tree->list(tx_rf_fe_root(chan) / "filters"); + for(size_t i = 0; i < names.size(); i++) + { + std::string name = tx_rf_fe_root(chan) / "filters" / names[i]; + if((search_mask.empty()) or (boost::contains(name, search_mask))) { + ret.push_back(name); + } + } + } + if (_tree->exists(rx_dsp_root(chan) / "filters")) { + std::vector names = _tree->list(tx_dsp_root(chan) / "filters"); + for(size_t i = 0; i < names.size(); i++) + { + std::string name = tx_dsp_root(chan) / "filters" / names[i]; + if((search_mask.empty()) or (boost::contains(name, search_mask))) { + ret.push_back(name); + } + } + } + + } + + return ret; + } + + filter_info_base::sptr get_filter(const std::string &path) + { + std::vector possible_names = get_filter_names(""); + std::vector::iterator it; + it = find(possible_names.begin(), possible_names.end(), path); + if (it == possible_names.end()) { + throw uhd::runtime_error("Attempting to get non-existing filter: "+path); + } + + return _tree->access(path / "value").get(); + } + + void set_filter(const std::string &path, filter_info_base::sptr filter) + { + std::vector possible_names = get_filter_names(""); + std::vector::iterator it; + it = find(possible_names.begin(), possible_names.end(), path); + if (it == possible_names.end()) { + throw uhd::runtime_error("Attempting to set non-existing filter: "+path); + } + + _tree->access(path / "value").set(filter); + } + /******************************************************************* * TX methods ******************************************************************/ -- cgit v1.2.3 From 21ccefb2facf3e85d0ab7146a6d4b93782688ade Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 11 Mar 2015 13:56:32 -0700 Subject: b200: Initialize _tick_rate properly to force tick rate update --- host/lib/usrp/b200/b200_impl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index 13169a5ed..e30853762 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -196,7 +196,8 @@ UHD_STATIC_BLOCK(register_b200_device) /*********************************************************************** * Structors **********************************************************************/ -b200_impl::b200_impl(const device_addr_t &device_addr) +b200_impl::b200_impl(const device_addr_t &device_addr) : + _tick_rate(0.0) // Forces a clock initialization at startup { _tree = property_tree::make(); _type = device::USRP; -- cgit v1.2.3 From 08467564116f4b948620e831bfd4b5426a43611c Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 11 Mar 2015 14:33:57 -0700 Subject: gpio: Renamed enums to avoid clash with generic, compiler-provided names --- host/lib/usrp/b200/b200_impl.cpp | 14 +++++++------- host/lib/usrp/cores/gpio_core_200.hpp | 21 +++++++++++++++++++-- host/lib/usrp/e300/e300_impl.cpp | 14 +++++++------- host/lib/usrp/x300/x300_impl.cpp | 14 +++++++------- 4 files changed, 40 insertions(+), 23 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index b1ab6ea7d..c22eb86bc 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -925,13 +925,13 @@ void b200_impl::set_fp_gpio(gpio_core_200::sptr gpio, const gpio_attr_t attr, co { 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); + case GPIO_CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value); + case GPIO_DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value); + case GPIO_OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value); + case GPIO_ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value); + case GPIO_ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value); + case GPIO_ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value); + case GPIO_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/cores/gpio_core_200.hpp b/host/lib/usrp/cores/gpio_core_200.hpp index a76cced01..e22834fd9 100644 --- a/host/lib/usrp/cores/gpio_core_200.hpp +++ b/host/lib/usrp/cores/gpio_core_200.hpp @@ -27,10 +27,27 @@ #include #include -typedef enum{CTRL,DDR,OUT,ATR_0X,ATR_RX,ATR_TX,ATR_XX} gpio_attr_t; +typedef enum { + GPIO_CTRL, + GPIO_DDR, + GPIO_OUT, + GPIO_ATR_0X, + GPIO_ATR_RX, + GPIO_ATR_TX, + GPIO_ATR_XX +} gpio_attr_t; + typedef std::map 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"); + boost::assign::map_list_of + (GPIO_CTRL, "CTRL") + (GPIO_DDR, "DDR") + (GPIO_OUT, "OUT") + (GPIO_ATR_0X, "ATR_0X") + (GPIO_ATR_RX, "ATR_RX") + (GPIO_ATR_TX, "ATR_TX") + (GPIO_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 ac92f9a12..8be3e47c9 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -587,19 +587,19 @@ void e300_impl::_set_internal_gpio( { switch (attr) { - case CTRL: + case GPIO_CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value); - case DDR: + case GPIO_DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value); - case OUT: + case GPIO_OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value); - case ATR_0X: + case GPIO_ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value); - case ATR_RX: + case GPIO_ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value); - case ATR_TX: + case GPIO_ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value); - case ATR_XX: + case GPIO_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.cpp b/host/lib/usrp/x300/x300_impl.cpp index a82be543d..d9b27b6b4 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -1542,13 +1542,13 @@ void x300_impl::set_fp_gpio(gpio_core_200::sptr gpio, const gpio_attr_t attr, co { 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); + case GPIO_CTRL: return gpio->set_pin_ctrl(dboard_iface::UNIT_RX, value); + case GPIO_DDR: return gpio->set_gpio_ddr(dboard_iface::UNIT_RX, value); + case GPIO_OUT: return gpio->set_gpio_out(dboard_iface::UNIT_RX, value); + case GPIO_ATR_0X: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, value); + case GPIO_ATR_RX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, value); + case GPIO_ATR_TX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, value); + case GPIO_ATR_XX: return gpio->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, value); default: UHD_THROW_INVALID_CODE_PATH(); } } -- cgit v1.2.3 From 4fa1f7825f090cdb5b7460ba5396fb79ea55e4c6 Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Sat, 7 Mar 2015 11:06:15 -0500 Subject: nirio: when unsupported, comment out unused variables. --- .../nirio/nirio_driver_iface_unsupported.cpp | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'host/lib') diff --git a/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp b/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp index 1a1142525..d265efa63 100644 --- a/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp +++ b/host/lib/transport/nirio/nirio_driver_iface_unsupported.cpp @@ -19,43 +19,43 @@ namespace nirio_driver_iface { nirio_status rio_open( - const std::string& device_path, - rio_dev_handle_t& device_handle) + const std::string& /* device_path */, + rio_dev_handle_t& /* device_handle */) { return NiRio_Status_FeatureNotSupported; } -void rio_close(rio_dev_handle_t& device_handle) +void rio_close(rio_dev_handle_t& /* device_handle */) { } -bool rio_isopen(rio_dev_handle_t device_handle) +bool rio_isopen(rio_dev_handle_t /* device_handle */) { return false; } nirio_status rio_ioctl( - rio_dev_handle_t device_handle, - uint32_t ioctl_code, - const void *write_buf, - size_t write_buf_len, - void *read_buf, - size_t read_buf_len) + rio_dev_handle_t /* device_handle */, + uint32_t /* ioctl_code */, + const void* /* write_buf */, + size_t /* write_buf_len */, + void* /* read_buf */, + size_t /* read_buf_len */) { return NiRio_Status_FeatureNotSupported; } nirio_status rio_mmap( - rio_dev_handle_t device_handle, - uint16_t memory_type, - size_t size, - bool writable, - rio_mmap_t &map) + rio_dev_handle_t /* device_handle */, + uint16_t /* memory_type */, + size_t /* size */, + bool /* writable */, + rio_mmap_t& /* map */) { return NiRio_Status_FeatureNotSupported; } -nirio_status rio_munmap(rio_mmap_t &map) +nirio_status rio_munmap(rio_mmap_t& /* map */) { return NiRio_Status_FeatureNotSupported; } -- cgit v1.2.3 From a4eee83b82a5f57b22c092e5f9dc825baf8fe6dd Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Sat, 7 Mar 2015 11:15:10 -0500 Subject: nirio: hopefully fix #pragma declarations; "push" and "pop" introduced in GCC 4.6; works with all clang. --- host/include/uhd/transport/nirio/nirio_fifo.ipp | 10 ++++++---- host/lib/transport/nirio/nirio_resource_manager.cpp | 11 ++++++----- host/lib/transport/nirio/niriok_proxy.cpp | 10 ++++++---- host/lib/transport/nirio/niriok_proxy_impl_v1.cpp | 11 ++++++----- host/lib/transport/nirio/niriok_proxy_impl_v2.cpp | 10 ++++++---- 5 files changed, 30 insertions(+), 22 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/transport/nirio/nirio_fifo.ipp b/host/include/uhd/transport/nirio/nirio_fifo.ipp index ca6486e30..49ce43888 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.ipp +++ b/host/include/uhd/transport/nirio/nirio_fifo.ipp @@ -15,9 +15,11 @@ // along with this program. If not, see . // -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -375,6 +377,6 @@ inline datatype_info_t nirio_fifo::_get_datatype_info() return datatype_info_t(RIO_SCALAR_TYPE_UQ, 8); } -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif diff --git a/host/lib/transport/nirio/nirio_resource_manager.cpp b/host/lib/transport/nirio/nirio_resource_manager.cpp index e56670de0..d62f5c40d 100644 --- a/host/lib/transport/nirio/nirio_resource_manager.cpp +++ b/host/lib/transport/nirio/nirio_resource_manager.cpp @@ -15,12 +15,13 @@ // along with this program. If not, see . // - #include -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -100,6 +101,6 @@ nirio_fifo_info_t* nirio_resource_manager::_lookup_fifo_info(const char* fifo_na }} -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif diff --git a/host/lib/transport/nirio/niriok_proxy.cpp b/host/lib/transport/nirio/niriok_proxy.cpp index cc2daba22..0cc13efb8 100644 --- a/host/lib/transport/nirio/niriok_proxy.cpp +++ b/host/lib/transport/nirio/niriok_proxy.cpp @@ -20,9 +20,11 @@ #include #include -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -73,6 +75,6 @@ namespace uhd { namespace niusrprio } }} -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif diff --git a/host/lib/transport/nirio/niriok_proxy_impl_v1.cpp b/host/lib/transport/nirio/niriok_proxy_impl_v1.cpp index f4a8e4ff5..f0ffe2ffc 100644 --- a/host/lib/transport/nirio/niriok_proxy_impl_v1.cpp +++ b/host/lib/transport/nirio/niriok_proxy_impl_v1.cpp @@ -15,13 +15,14 @@ // along with this program. If not, see . // - #include #include -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -490,6 +491,6 @@ namespace uhd { namespace niusrprio }} -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif diff --git a/host/lib/transport/nirio/niriok_proxy_impl_v2.cpp b/host/lib/transport/nirio/niriok_proxy_impl_v2.cpp index 8fb82708e..748db5cf8 100644 --- a/host/lib/transport/nirio/niriok_proxy_impl_v2.cpp +++ b/host/lib/transport/nirio/niriok_proxy_impl_v2.cpp @@ -19,9 +19,11 @@ #include #include -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -642,6 +644,6 @@ namespace uhd { namespace niusrprio }} -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif -- cgit v1.2.3 From a7049e4ff79cdc205db76bf7270219f254073961 Mon Sep 17 00:00:00 2001 From: Michael Dickens Date: Sat, 7 Mar 2015 11:12:58 -0500 Subject: uhd: Fixed multiple compiler warnings - Use ULL and LL etc. so compiler doesn't need to decide constant's types - define the empty 'while' loop to include {} to make older compilers happy - Use explicit type names for BOOST_CHECK_EQUAL --- host/examples/test_clock_synch.cpp | 8 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- .../usrp/common/ad9361_driver/ad9361_synth_lut.h | 28 ++--- host/tests/chdr_test.cpp | 10 +- host/tests/fp_compare_delta_test.cpp | 6 +- host/tests/sid_t_test.cpp | 122 ++++++++++----------- host/tests/sph_recv_test.cpp | 4 +- host/tests/sph_send_test.cpp | 2 +- host/tests/time_spec_test.cpp | 4 +- 9 files changed, 93 insertions(+), 93 deletions(-) (limited to 'host/lib') diff --git a/host/examples/test_clock_synch.cpp b/host/examples/test_clock_synch.cpp index 7a4226345..50a1444f8 100644 --- a/host/examples/test_clock_synch.cpp +++ b/host/examples/test_clock_synch.cpp @@ -35,14 +35,14 @@ using namespace uhd::usrp_clock; using namespace uhd::usrp; void wait_for_pps(multi_usrp::sptr usrp, size_t chan, double timeout){ - boost::uint32_t last_pps_time = usrp->get_time_last_pps(chan).get_full_secs(); - boost::uint32_t system_time = uhd::time_spec_t::get_system_time().get_full_secs(); - boost::uint32_t exit_time = system_time + timeout; + time_t last_pps_time = usrp->get_time_last_pps(chan).get_full_secs(); + time_t system_time = uhd::time_spec_t::get_system_time().get_full_secs(); + time_t exit_time = system_time + timeout; bool detected_pps = false; //Otherwise, this would hang if the USRP doesn't detect any PPS while(uhd::time_spec_t::get_system_time().get_full_secs() < exit_time){ - boost::uint32_t time_now = usrp->get_time_last_pps(chan).get_full_secs(); + time_t time_now = usrp->get_time_last_pps(chan).get_full_secs(); if(last_pps_time < time_now){ detected_pps = true; break; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 5c84327a4..c3c2b8e97 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -147,7 +147,7 @@ public: */ void set_xport_chan_get_buff(const size_t xport_chan, const get_buff_type &get_buff, const bool flush = false){ if (flush){ - while (get_buff(0.0)); + while (get_buff(0.0)) {}; } _props.at(xport_chan).get_buff = get_buff; } diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_synth_lut.h b/host/lib/usrp/common/ad9361_driver/ad9361_synth_lut.h index cb320e1f4..0475a5eb1 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_synth_lut.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_synth_lut.h @@ -6,20 +6,20 @@ #define INCLUDED_AD9361_SYNTH_LUT_HPP -double vco_index[53] = {12605000000, 12245000000, 11906000000, 11588000000, - 11288000000, 11007000000, 10742000000, 10492000000, - 10258000000, 10036000000, 9827800000, 9631100000, - 9445300000, 9269800000, 9103600000, 8946300000, - 8797000000, 8655300000, 8520600000, 8392300000, - 8269900000, 8153100000, 8041400000, 7934400000, - 7831800000, 7733200000, 7638400000, 7547100000, - 7459000000, 7374000000, 7291900000, 7212400000, - 7135500000, 7061000000, 6988700000, 6918600000, - 6850600000, 6784600000, 6720500000, 6658200000, - 6597800000, 6539200000, 6482300000, 6427000000, - 6373400000, 6321400000, 6270900000, 6222000000, - 6174500000, 6128400000, 6083600000, 6040100000, - 5997700000}; +double vco_index[53] = {12605000000.0, 12245000000.0, 11906000000.0, 11588000000.0, + 11288000000.0, 11007000000.0, 10742000000.0, 10492000000.0, + 10258000000.0, 10036000000.0, 9827800000.0, 9631100000.0, + 9445300000.0, 9269800000.0, 9103600000.0, 8946300000.0, + 8797000000.0, 8655300000.0, 8520600000.0, 8392300000.0, + 8269900000.0, 8153100000.0, 8041400000.0, 7934400000.0, + 7831800000.0, 7733200000.0, 7638400000.0, 7547100000.0, + 7459000000.0, 7374000000.0, 7291900000.0, 7212400000.0, + 7135500000.0, 7061000000.0, 6988700000.0, 6918600000.0, + 6850600000.0, 6784600000.0, 6720500000.0, 6658200000.0, + 6597800000.0, 6539200000.0, 6482300000.0, 6427000000.0, + 6373400000.0, 6321400000.0, 6270900000.0, 6222000000.0, + 6174500000.0, 6128400000.0, 6083600000.0, 6040100000.0, + 5997700000.0}; int synth_cal_lut[53][12] = { {10, 0, 4, 0, 15, 8, 8, 13, 4, 13, 15, 9}, {10, 0, 4, 0, 15, 8, 9, 13, 4, 13, 15, 9}, diff --git a/host/tests/chdr_test.cpp b/host/tests/chdr_test.cpp index 8893e12e5..ed6c690f9 100644 --- a/host/tests/chdr_test.cpp +++ b/host/tests/chdr_test.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(test_with_chdr){ if_packet_info.eob = false; if_packet_info.packet_count = 7; if_packet_info.has_tsf = true; - if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.tsf = 0x1234567890ABCDEFull; if_packet_info.sid = 0xAABBCCDD; if_packet_info.num_payload_words32 = 24; if_packet_info.num_payload_bytes = 95; @@ -94,7 +94,7 @@ BOOST_AUTO_TEST_CASE(test_with_chdr_fc){ if_packet_info.eob = false; if_packet_info.packet_count = 19; if_packet_info.has_tsf = false; - if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.tsf = 0x1234567890ABCDEFull; if_packet_info.sid = 0xAABBCCDD; if_packet_info.num_payload_words32 = 4; if_packet_info.num_payload_bytes = 16; @@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(test_with_chdr_cmd){ if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_CMD; if_packet_info.packet_count = 19; if_packet_info.has_tsf = true; - if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.tsf = 0x1234567890ABCDEFull; if_packet_info.sid = 0xAABBCCDD; if_packet_info.num_payload_words32 = 4; if_packet_info.num_payload_bytes = 16; @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(test_with_chdr_resp){ if_packet_info.packet_type = if_packet_info_t::PACKET_TYPE_RESP; if_packet_info.packet_count = 123; if_packet_info.has_tsf = false; - if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.tsf = 0x1234567890ABCDEFull; if_packet_info.sid = 0xAABBCCDD; if_packet_info.num_payload_words32 = 4; if_packet_info.num_payload_bytes = 16; @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(test_with_chdr_err){ if_packet_info.eob = false; if_packet_info.error = false; // Needs to be set explicitly if_packet_info.has_tsf = false; - if_packet_info.tsf = 0x1234567890ABCDEF; + if_packet_info.tsf = 0x1234567890ABCDEFull; if_packet_info.sid = 0xAABBCCDD; if_packet_info.num_payload_words32 = 4; if_packet_info.num_payload_bytes = 16; diff --git a/host/tests/fp_compare_delta_test.cpp b/host/tests/fp_compare_delta_test.cpp index 9b009a79d..a38c3d2b0 100644 --- a/host/tests/fp_compare_delta_test.cpp +++ b/host/tests/fp_compare_delta_test.cpp @@ -239,12 +239,12 @@ BOOST_AUTO_TEST_CASE(double_greaterthanequals_operators) { BOOST_AUTO_TEST_CASE(frequency_compare_function) { - BOOST_CHECK(uhd::math::frequencies_are_equal(6817333232, 6817333232)); - BOOST_CHECK(!uhd::math::frequencies_are_equal(6817333233, 6817333232)); + BOOST_CHECK(uhd::math::frequencies_are_equal(6817333232.0, 6817333232.0)); + BOOST_CHECK(!uhd::math::frequencies_are_equal(6817333233.0, 6817333232.0)); BOOST_CHECK(uhd::math::frequencies_are_equal(6817333232.1, 6817333232.1)); BOOST_CHECK(!uhd::math::frequencies_are_equal(6817333232.5, 6817333232.6)); BOOST_CHECK(uhd::math::frequencies_are_equal(16.8173332321e9, 16.8173332321e9)); BOOST_CHECK(!uhd::math::frequencies_are_equal(16.8173332322e9, 16.8173332321e9)); BOOST_CHECK(!uhd::math::frequencies_are_equal(5.0, 4.0)); - BOOST_CHECK(uhd::math::frequencies_are_equal(48750000, 48749999.9946)); + BOOST_CHECK(uhd::math::frequencies_are_equal(48750000.0, 48749999.9946)); } diff --git a/host/tests/sid_t_test.cpp b/host/tests/sid_t_test.cpp index 71ab2c213..b5cdeb3d8 100644 --- a/host/tests/sid_t_test.cpp +++ b/host/tests/sid_t_test.cpp @@ -30,12 +30,12 @@ BOOST_AUTO_TEST_CASE(test_sid_t) { BOOST_CHECK_EQUAL(sid.is_set(), true); BOOST_CHECK_EQUAL(sid.to_pp_string(), "1.2>3.16"); BOOST_CHECK_EQUAL(sid.to_pp_string_hex(), "01:02>03:10"); - BOOST_CHECK_EQUAL(sid.get_src(), 0x0102); - BOOST_CHECK_EQUAL(sid.get_dst(), 0x0310); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x01); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x10); + BOOST_CHECK_EQUAL(sid.get_src(), (uint32_t)0x0102); + BOOST_CHECK_EQUAL(sid.get_dst(), (uint32_t)0x0310); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x01); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x10); BOOST_CHECK_EQUAL(sid == sid, true); BOOST_CHECK_EQUAL(sid == sid_value, true); @@ -68,88 +68,88 @@ BOOST_AUTO_TEST_CASE(test_sid_t_set) { sid_t sid(sid_value); sid.set(0x01020304); - BOOST_CHECK_EQUAL(sid.get(), 0x01020304); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x01); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); - BOOST_CHECK_EQUAL(sid.get_dst_xbarport(), 0x0); - BOOST_CHECK_EQUAL(sid.get_dst_blockport(), 0x4); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x01020304); + BOOST_CHECK_EQUAL(sid.get_src_addr(),(uint32_t)0x01); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); + BOOST_CHECK_EQUAL(sid.get_dst_xbarport(), (uint32_t)0x0); + BOOST_CHECK_EQUAL(sid.get_dst_blockport(), (uint32_t)0x4); sid.set_src_addr(0x0a); - BOOST_CHECK_EQUAL(sid.get(), 0x0a020304); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x02); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a020304); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x02); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); sid.set_src_endpoint(0x0b); - BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0304); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x03); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0304); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x03); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); sid.set_dst_addr(0x0c); - BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0c04); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x04); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0c04); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x04); sid.set_dst_endpoint(0x0d); - BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0c0d); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0x0d); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0c0d); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0x0d); sid.set_dst_xbarport(0xb); - BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0cbd); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0xbd); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0cbd); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0xbd); sid.set_dst_blockport(0xc); - BOOST_CHECK_EQUAL(sid.get(), 0x0a0b0cbc); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 0x0a); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 0x0b); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 0x0c); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 0xbc); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0a0b0cbc); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)0x0a); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)0x0b); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)0x0c); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)0xbc); sid_t flipped_sid = sid.reversed(); - BOOST_CHECK_EQUAL(flipped_sid.get(), 0x0cbc0a0b); + BOOST_CHECK_EQUAL(flipped_sid.get(), (uint32_t)0x0cbc0a0b); // In-place sid.reverse(); - BOOST_CHECK_EQUAL(sid.get(), 0x0cbc0a0b); + BOOST_CHECK_EQUAL(sid.get(), (uint32_t)0x0cbc0a0b); } BOOST_AUTO_TEST_CASE(test_sid_t_from_str) { sid_t sid("1.2>3.4"); - BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 4); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)4); sid = "01:02>03:10"; - BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); sid = "01:06/03:10"; - BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 6); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 3); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)6); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)3); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); sid = "01:02:04:10"; - BOOST_CHECK_EQUAL(sid.get_src_addr(), 1); - BOOST_CHECK_EQUAL(sid.get_src_endpoint(), 2); - BOOST_CHECK_EQUAL(sid.get_dst_addr(), 4); - BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), 16); + BOOST_CHECK_EQUAL(sid.get_src_addr(), (uint32_t)1); + BOOST_CHECK_EQUAL(sid.get_src_endpoint(), (uint32_t)2); + BOOST_CHECK_EQUAL(sid.get_dst_addr(), (uint32_t)4); + BOOST_CHECK_EQUAL(sid.get_dst_endpoint(), (uint32_t)16); BOOST_REQUIRE_THROW(sid_t fail_sid("foobar"), uhd::value_error); BOOST_REQUIRE_THROW(sid_t fail_sid("01:02:03:4"), uhd::value_error); diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 5dd0761db..e8c51b847 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(metadata.has_time_spec); BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); - BOOST_CHECK_EQUAL(num_samps_ret, 10); + BOOST_CHECK_EQUAL(num_samps_ret, (size_t)10); num_accum_samps += num_samps_ret; if (not metadata.more_fragments) continue; @@ -685,7 +685,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); - BOOST_CHECK_EQUAL(metadata.fragment_offset, 10); + BOOST_CHECK_EQUAL(metadata.fragment_offset, (size_t)10); BOOST_CHECK(metadata.has_time_spec); BOOST_CHECK_TS_CLOSE(metadata.time_spec, uhd::time_spec_t::from_ticks(num_accum_samps, SAMP_RATE)); BOOST_CHECK_EQUAL(num_samps_ret, i%10); diff --git a/host/tests/sph_send_test.cpp b/host/tests/sph_send_test.cpp index 603b36c85..58d47c76d 100644 --- a/host/tests/sph_send_test.cpp +++ b/host/tests/sph_send_test.cpp @@ -182,7 +182,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; dummy_send_xport.pop_front_packet(ifpi); - BOOST_CHECK_EQUAL(ifpi.num_payload_words32, 20); + BOOST_CHECK_EQUAL(ifpi.num_payload_words32, (size_t)20); BOOST_CHECK(ifpi.has_tsf); BOOST_CHECK_EQUAL(ifpi.tsf, num_accum_samps*TICK_RATE/SAMP_RATE); BOOST_CHECK_EQUAL(ifpi.sob, i == 0); diff --git a/host/tests/time_spec_test.cpp b/host/tests/time_spec_test.cpp index c9b9652f9..b98bea7d9 100644 --- a/host/tests/time_spec_test.cpp +++ b/host/tests/time_spec_test.cpp @@ -112,8 +112,8 @@ BOOST_AUTO_TEST_CASE(test_time_large_ticks_to_time_spec) BOOST_AUTO_TEST_CASE(test_time_error_irrational_rate) { - static const double rate = 1625e3/6; - const long long tick_in = 23423436291667; + static const double rate = 1625e3/6.0; + const long long tick_in = 23423436291667ll; const uhd::time_spec_t ts = uhd::time_spec_t::from_ticks(tick_in, rate); const long long tick_out = ts.to_ticks(rate); const long long err = tick_in - tick_out; -- cgit v1.2.3 From fae746179cbb1d8ac146dcae9b5d6cb58b366a56 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 11 Mar 2015 16:14:00 -0700 Subject: uhd: Fixed multiple compiler warnings (unused variables, missing literal f) --- host/include/uhd/utils/math.hpp | 2 +- host/lib/usrp/b200/b200_impl.cpp | 2 +- host/lib/usrp/dboard/db_ubx.cpp | 2 +- host/lib/usrp/multi_usrp.cpp | 12 ++++++------ host/lib/usrp_clock/octoclock/octoclock_impl.cpp | 2 +- host/utils/b2xx_fx3_utils.cpp | 4 ++-- host/utils/query_gpsdo_sensors.cpp | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) (limited to 'host/lib') diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp index 21825c3dc..e6ac4d3dc 100644 --- a/host/include/uhd/utils/math.hpp +++ b/host/include/uhd/utils/math.hpp @@ -60,7 +60,7 @@ namespace math { * values, a custom epsilon should be defined for those computations. This * use-case is provided for in the `fp_compare_epsilon` class constructor. */ - static const float SINGLE_PRECISION_EPSILON = 1.19e-7; + static const float SINGLE_PRECISION_EPSILON = 1.19e-7f; static const double DOUBLE_PRECISION_EPSILON = 2.22e-16; namespace fp_compare { diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index e30853762..304a3fc48 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -1007,6 +1007,6 @@ sensor_value_t b200_impl::get_ref_locked(void) sensor_value_t b200_impl::get_fe_pll_locked(const bool is_tx) { const boost::uint32_t st = _local_ctrl->peek32(RB32_CORE_PLL); - const bool locked = is_tx ? st & 0x1 : st & 0x2; + const bool locked = is_tx ? bool(st & 0x1) : bool(st & 0x2); return sensor_value_t("LO", locked, "locked", "unlocked"); } diff --git a/host/lib/usrp/dboard/db_ubx.cpp b/host/lib/usrp/dboard/db_ubx.cpp index b6cc1421c..5184d2ecb 100644 --- a/host/lib/usrp/dboard/db_ubx.cpp +++ b/host/lib/usrp/dboard/db_ubx.cpp @@ -84,7 +84,7 @@ protected: // Get only regs with changes try { changed_regs = get_changed_addrs(); - } catch (uhd::runtime_error& e) { + } catch (uhd::runtime_error&) { // No saved state - write all regs for (int addr = 5; addr >= 0; addr--) changed_regs.insert(boost::uint32_t(addr)); diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 175633c4c..45e736757 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -823,7 +823,7 @@ public: void set_rx_gain(double gain, const std::string &name, size_t chan){ try { return rx_gain_group(chan)->set_value(gain, name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,rx); } } @@ -831,7 +831,7 @@ public: double get_rx_gain(const std::string &name, size_t chan){ try { return rx_gain_group(chan)->get_value(name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,rx); } } @@ -839,7 +839,7 @@ public: gain_range_t get_rx_gain_range(const std::string &name, size_t chan){ try { return rx_gain_group(chan)->get_range(name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,rx); } } @@ -1024,7 +1024,7 @@ public: void set_tx_gain(double gain, const std::string &name, size_t chan){ try { return tx_gain_group(chan)->set_value(gain, name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,tx); } } @@ -1032,7 +1032,7 @@ public: double get_tx_gain(const std::string &name, size_t chan){ try { return tx_gain_group(chan)->get_value(name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,tx); } } @@ -1040,7 +1040,7 @@ public: gain_range_t get_tx_gain_range(const std::string &name, size_t chan){ try { return tx_gain_group(chan)->get_range(name); - } catch (uhd::key_error &e) { + } catch (uhd::key_error &) { THROW_GAIN_NAME_ERROR(name,chan,tx); } } diff --git a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp index d55fab10e..b98d95725 100644 --- a/host/lib/usrp_clock/octoclock/octoclock_impl.cpp +++ b/host/lib/usrp_clock/octoclock/octoclock_impl.cpp @@ -417,7 +417,7 @@ std::string octoclock_impl::_get_images_help_message(const std::string &addr){ try{ image_location = uhd::find_image_path(image_name); } - catch(const std::exception &e){ + catch(const std::exception &){ return str(boost::format("Could not find %s in your images path.\n%s") % image_name % uhd::print_utility_error("uhd_images_downloader.py")); diff --git a/host/utils/b2xx_fx3_utils.cpp b/host/utils/b2xx_fx3_utils.cpp index 8b64be63e..572daef70 100644 --- a/host/utils/b2xx_fx3_utils.cpp +++ b/host/utils/b2xx_fx3_utils.cpp @@ -173,7 +173,7 @@ uhd::transport::usb_device_handle::sptr open_device(const boost::uint16_t vid, c if (!handle) std::cerr << "Cannot open device" << std::endl; } - catch(const std::exception &e) { + catch(const std::exception &) { std::cerr << "Failed to communicate with the device!" << std::endl; #ifdef UHD_PLATFORM_WIN32 std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details:\nhttp://files.ettus.com/manual/page_transport.html" << std::endl; @@ -195,7 +195,7 @@ b200_iface::sptr make_b200_iface(const uhd::transport::usb_device_handle::sptr & if (!b200) std::cerr << "Cannot create device interface" << std::endl; } - catch(const std::exception &e) { + catch(const std::exception &) { std::cerr << "Failed to communicate with the device!" << std::endl; #ifdef UHD_PLATFORM_WIN32 std::cerr << "The necessary drivers are not installed. Read the UHD Transport Application Notes for details:\nhttp://files.ettus.com/manual/page_transport.html" << std::endl; diff --git a/host/utils/query_gpsdo_sensors.cpp b/host/utils/query_gpsdo_sensors.cpp index 05f918eb4..9a40d2b42 100644 --- a/host/utils/query_gpsdo_sensors.cpp +++ b/host/utils/query_gpsdo_sensors.cpp @@ -118,7 +118,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::sensor_value_t rmc_string = usrp->get_mboard_sensor("gps_gprmc"); std::cout << boost::format("Printing available NMEA strings:\n"); std::cout << boost::format("%s\n%s\n%s\n") % gga_string.to_pp_string() % rmc_string.to_pp_string() % gps_time.to_pp_string(); - } catch (std::exception &e) { + } catch (std::exception &) { std::cout << "NMEA strings not implemented for this device." << std::endl; } std::cout << boost::format("UHD Device time: %.0f seconds\n") % (last_pps_time.get_real_secs()); -- cgit v1.2.3 From cc7d37f114d5a14b4e45372f38324bf95115b6b9 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Wed, 11 Mar 2015 16:45:19 -0700 Subject: uhd: Fixed several type-cast related warnings for naggy compilers --- host/examples/txrx_loopback_to_file.cpp | 4 ++-- host/include/uhd/utils/fp_compare_delta.ipp | 20 +++++++++--------- host/include/uhd/utils/math.hpp | 2 +- host/lib/usrp/cores/rx_dsp_core_3000.cpp | 2 +- host/lib/usrp/cores/time_core_3000.cpp | 6 +++--- host/lib/usrp/dboard/db_cbx.cpp | 2 +- host/lib/usrp/multi_usrp.cpp | 2 +- host/tests/fp_compare_delta_test.cpp | 26 +++++++++++------------ host/tests/fp_compare_epsilon_test.cpp | 32 ++++++++++++++--------------- host/utils/usrp_cal_utils.hpp | 2 +- 10 files changed, 49 insertions(+), 49 deletions(-) (limited to 'host/lib') diff --git a/host/examples/txrx_loopback_to_file.cpp b/host/examples/txrx_loopback_to_file.cpp index 4eb6daa6c..efa23c410 100644 --- a/host/examples/txrx_loopback_to_file.cpp +++ b/host/examples/txrx_loopback_to_file.cpp @@ -182,7 +182,7 @@ template void recv_to_file( UHD_ASSERT_THROW(outfiles.size() == buffs.size()); UHD_ASSERT_THROW(buffs.size() == rx_channel_nums.size()); bool overflow_message = true; - float timeout = settling_time + 0.1; //expected settling time + padding for first recv + float timeout = settling_time + 0.1f; //expected settling time + padding for first recv //setup streaming uhd::stream_cmd_t stream_cmd((num_requested_samples == 0)? @@ -196,7 +196,7 @@ template void recv_to_file( while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)){ size_t num_rx_samps = rx_stream->recv(buff_ptrs, samps_per_buff, md, timeout); - timeout = 0.1; //small timeout for subsequent recv + timeout = 0.1f; //small timeout for subsequent recv if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) { std::cout << boost::format("Timeout while streaming") << std::endl; diff --git a/host/include/uhd/utils/fp_compare_delta.ipp b/host/include/uhd/utils/fp_compare_delta.ipp index 092ade6e9..49cbc281b 100644 --- a/host/include/uhd/utils/fp_compare_delta.ipp +++ b/host/include/uhd/utils/fp_compare_delta.ipp @@ -100,8 +100,8 @@ namespace uhd { namespace math { namespace fp_compare { template UHD_INLINE bool operator==(fp_compare_delta lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return (std::fabs(lhs._value - rhs) < delta); } @@ -112,8 +112,8 @@ namespace uhd { namespace math { namespace fp_compare { template UHD_INLINE bool operator<(fp_compare_delta lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return ((rhs - lhs._value) > delta); } @@ -124,8 +124,8 @@ namespace uhd { namespace math { namespace fp_compare { template UHD_INLINE bool operator>(fp_compare_delta lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return ((lhs._value - rhs) > delta); } @@ -148,8 +148,8 @@ namespace uhd { namespace math { namespace fp_compare { template UHD_INLINE bool operator<(double lhs, fp_compare_delta rhs) { - float_t delta = fp_compare_select_delta(DOUBLE_PRECISION_DELTA, - double(rhs._delta)); + float_t delta = float_t(fp_compare_select_delta(DOUBLE_PRECISION_DELTA, + double(rhs._delta))); return ((rhs._value - lhs) > delta); } @@ -160,8 +160,8 @@ namespace uhd { namespace math { namespace fp_compare { template UHD_INLINE bool operator>(double lhs, fp_compare_delta rhs) { - float_t delta = fp_compare_select_delta(DOUBLE_PRECISION_DELTA, - double(rhs._delta)); + float_t delta = float_t(fp_compare_select_delta(DOUBLE_PRECISION_DELTA, + double(rhs._delta))); return ((lhs - rhs._value) > delta); } diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp index e6ac4d3dc..4f88494d6 100644 --- a/host/include/uhd/utils/math.hpp +++ b/host/include/uhd/utils/math.hpp @@ -155,7 +155,7 @@ namespace fp_compare { * These are the default deltas used by the 'fp_compare_delta' class for * single and double-precision floating point comparisons. */ - static const float SINGLE_PRECISION_DELTA = 1e-3; + static const float SINGLE_PRECISION_DELTA = 1e-3f; static const double DOUBLE_PRECISION_DELTA = 1e-5; /*! Floating-point delta to use for frequency comparisons. */ diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.cpp b/host/lib/usrp/cores/rx_dsp_core_3000.cpp index 13d69920a..8a131ffb4 100644 --- a/host/lib/usrp/cores/rx_dsp_core_3000.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_3000.cpp @@ -72,7 +72,7 @@ public: { UHD_SAFE_CALL ( - //NOP + ;//NOP ) } diff --git a/host/lib/usrp/cores/time_core_3000.cpp b/host/lib/usrp/cores/time_core_3000.cpp index aa5d5593d..ffae5dc0d 100644 --- a/host/lib/usrp/cores/time_core_3000.cpp +++ b/host/lib/usrp/cores/time_core_3000.cpp @@ -50,7 +50,7 @@ struct time_core_3000_impl : time_core_3000 { UHD_SAFE_CALL ( - //NOP + ;//NOP ) } @@ -71,8 +71,8 @@ struct time_core_3000_impl : time_core_3000 UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl; //useful warning for debugging actual rate - const size_t ticks_elapsed = _tick_rate*approx_secs; - const size_t appox_rate = ticks_elapsed/(sleep_millis/1e3); + const size_t ticks_elapsed = size_t(_tick_rate*approx_secs); + const size_t appox_rate = size_t(ticks_elapsed/(sleep_millis/1e3)); if (test_fail) UHD_MSG(warning) << "Expecting clock rate: " << (_tick_rate/1e6) << " MHz\n" << "Appoximate clock rate: " << (appox_rate/1e6) << " MHz\n" diff --git a/host/lib/usrp/dboard/db_cbx.cpp b/host/lib/usrp/dboard/db_cbx.cpp index db7f84932..ad255460e 100644 --- a/host/lib/usrp/dboard/db_cbx.cpp +++ b/host/lib/usrp/dboard/db_cbx.cpp @@ -142,7 +142,7 @@ double sbx_xcvr::cbx::set_lo_freq(dboard_iface::unit_t unit, double target_freq) } //keep pfd freq low enough to achieve 50kHz BS clock - BS = std::ceil(pfd_freq / 50e3); + BS = int(std::ceil(pfd_freq / 50e3)); if(BS <= 1023) break; } diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 45e736757..794438b90 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -1162,7 +1162,7 @@ public: { if (_tree->exists(mb_root(mboard) / "gpio" / bank)) { - return _tree->access(mb_root(mboard) / "gpio" / bank / attr).get(); + return boost::uint32_t(_tree->access(mb_root(mboard) / "gpio" / bank / attr).get()); } if (bank.size() > 2 and bank[1] == 'X') { diff --git a/host/tests/fp_compare_delta_test.cpp b/host/tests/fp_compare_delta_test.cpp index 9b009a79d..0ac4e257d 100644 --- a/host/tests/fp_compare_delta_test.cpp +++ b/host/tests/fp_compare_delta_test.cpp @@ -101,8 +101,8 @@ BOOST_AUTO_TEST_CASE(double_equality_operators) { BOOST_AUTO_TEST_CASE(float_inequality_operators) { // Test inequality operator, which is based on equality operator - fp_compare_delta alpha = fp_compare_delta(127.0); - fp_compare_delta beta = fp_compare_delta(alpha._value + 1.19e-3); + fp_compare_delta alpha = fp_compare_delta(127.0f); + fp_compare_delta beta = fp_compare_delta(alpha._value + 1.19e-3f); BOOST_CHECK(alpha != beta); BOOST_CHECK(alpha != float(alpha._value + 1.19e-3)); @@ -119,17 +119,17 @@ BOOST_AUTO_TEST_CASE(double_inequality_operators) { BOOST_AUTO_TEST_CASE(float_lessthan_operators) { // Test less-than operator - fp_compare_delta alpha = fp_compare_delta(274192.7); - fp_compare_delta beta = fp_compare_delta(alpha._value - 0.2); + fp_compare_delta alpha = fp_compare_delta(274192.7f); + fp_compare_delta beta = fp_compare_delta(alpha._value - 0.2f); BOOST_CHECK(beta < alpha); BOOST_CHECK(float(alpha._value - 0.2) < alpha); // Confirm false less-than case - fp_compare_delta charlie = fp_compare_delta(alpha._value - 1.2); + fp_compare_delta charlie = fp_compare_delta(alpha._value - 1.2f); BOOST_CHECK(not (alpha < charlie)); - BOOST_CHECK(not (alpha < float(alpha._value - 1.2))); + BOOST_CHECK(not (alpha < float(alpha._value - 1.2f))); } BOOST_AUTO_TEST_CASE(double_lessthan_operators) { @@ -149,14 +149,14 @@ BOOST_AUTO_TEST_CASE(double_lessthan_operators) { BOOST_AUTO_TEST_CASE(float_lessthanequals_operators) { // Test that <= correctly reports for equal values - fp_compare_delta alpha = fp_compare_delta(827.3); + fp_compare_delta alpha = fp_compare_delta(827.3f); fp_compare_delta beta = fp_compare_delta(alpha._value); BOOST_CHECK(alpha <= beta); BOOST_CHECK(alpha <= float(alpha._value)); // Test that <= correctly reports for less-than values - fp_compare_delta charlie = fp_compare_delta(alpha._value - 1.2); + fp_compare_delta charlie = fp_compare_delta(alpha._value - 1.2f); BOOST_CHECK(charlie <= alpha); BOOST_CHECK(float(alpha._value - 1.2) <= alpha); @@ -179,14 +179,14 @@ BOOST_AUTO_TEST_CASE(double_lessthanequals_operators) { BOOST_AUTO_TEST_CASE(float_greaterthan_operators) { // Test basic greater-than functionality - fp_compare_delta alpha = fp_compare_delta(98325.4); - fp_compare_delta beta = fp_compare_delta(alpha._value + 0.15); + fp_compare_delta alpha = fp_compare_delta(98325.4f); + fp_compare_delta beta = fp_compare_delta(alpha._value + 0.15f); BOOST_CHECK(beta > alpha); BOOST_CHECK(float(alpha._value + 0.15) > alpha); // Test false greater-than case - fp_compare_delta charlie = fp_compare_delta(alpha._value + 1.2); + fp_compare_delta charlie = fp_compare_delta(alpha._value + 1.2f); BOOST_CHECK(not (alpha > charlie)); BOOST_CHECK(not (alpha > float(alpha._value + 1.2))); @@ -209,14 +209,14 @@ BOOST_AUTO_TEST_CASE(double_greaterthan_operators) { BOOST_AUTO_TEST_CASE(float_greaterthanequals_operators) { // Test that >= correctly reports for equal values - fp_compare_delta alpha = fp_compare_delta(7834.89); + fp_compare_delta alpha = fp_compare_delta(7834.89f); fp_compare_delta beta = fp_compare_delta(alpha._value); BOOST_CHECK(alpha >= beta); BOOST_CHECK(alpha >= float(alpha._value)); // Test that >= correctly reports for greater-than values - fp_compare_delta charlie = fp_compare_delta(alpha._value + 4.8); + fp_compare_delta charlie = fp_compare_delta(alpha._value + 4.8f); BOOST_CHECK(charlie >= alpha); BOOST_CHECK(float(alpha._value + 4.8) >= alpha); diff --git a/host/tests/fp_compare_epsilon_test.cpp b/host/tests/fp_compare_epsilon_test.cpp index 5790318c2..45687ad26 100644 --- a/host/tests/fp_compare_epsilon_test.cpp +++ b/host/tests/fp_compare_epsilon_test.cpp @@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(fp_compare_epsilon_constructors) { // Test constructor with specified epsilon fp_compare_epsilon foxtrot = fp_compare_epsilon(alpha._value, uhd::math::SINGLE_PRECISION_EPSILON); - fp_compare_epsilon gamma = fp_compare_epsilon(alpha._value, 2.0e-1); + fp_compare_epsilon gamma = fp_compare_epsilon(alpha._value, 2.0e-1f); BOOST_CHECK_EQUAL(alpha._epsilon, foxtrot._epsilon); BOOST_CHECK(not (alpha._epsilon == gamma._epsilon)); @@ -102,10 +102,10 @@ BOOST_AUTO_TEST_CASE(double_equality_operators) { BOOST_AUTO_TEST_CASE(float_inequality_operators) { // Test inequality operator, which is based on equality operator fp_compare_epsilon alpha = fp_compare_epsilon(127.0); - fp_compare_epsilon beta = fp_compare_epsilon(alpha._value + 1.19e-5); + fp_compare_epsilon beta = fp_compare_epsilon(alpha._value + 1.19e-5f); BOOST_CHECK(alpha != beta); - BOOST_CHECK(alpha != float(alpha._value + 1.19e-5)); + BOOST_CHECK(alpha != float(alpha._value + 1.19e-5f)); } BOOST_AUTO_TEST_CASE(double_inequality_operators) { @@ -119,17 +119,17 @@ BOOST_AUTO_TEST_CASE(double_inequality_operators) { BOOST_AUTO_TEST_CASE(float_lessthan_operators) { // Test less-than operator - fp_compare_epsilon alpha = fp_compare_epsilon(274192.7); - fp_compare_epsilon beta = fp_compare_epsilon(alpha._value - 0.15); + fp_compare_epsilon alpha = fp_compare_epsilon(274192.7f); + fp_compare_epsilon beta = fp_compare_epsilon(alpha._value - 0.15f); BOOST_CHECK(beta < alpha); BOOST_CHECK(float(alpha._value - 0.15) < alpha); // Confirm false less-than case - fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value - 1.2); + fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value - 1.2f); BOOST_CHECK(not (alpha < charlie)); - BOOST_CHECK(not (alpha < float(alpha._value - 1.2))); + BOOST_CHECK(not (alpha < float(alpha._value - 1.2f))); } BOOST_AUTO_TEST_CASE(double_lessthan_operators) { @@ -149,14 +149,14 @@ BOOST_AUTO_TEST_CASE(double_lessthan_operators) { BOOST_AUTO_TEST_CASE(float_lessthanequals_operators) { // Test that <= correctly reports for equal values - fp_compare_epsilon alpha = fp_compare_epsilon(827.3); + fp_compare_epsilon alpha = fp_compare_epsilon(827.3f); fp_compare_epsilon beta = fp_compare_epsilon(alpha._value); BOOST_CHECK(alpha <= beta); BOOST_CHECK(alpha <= float(alpha._value)); // Test that <= correctly reports for less-than values - fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value - 1.2); + fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value - 1.2f); BOOST_CHECK(charlie <= alpha); BOOST_CHECK(float(alpha._value - 1.2) <= alpha); @@ -179,17 +179,17 @@ BOOST_AUTO_TEST_CASE(double_lessthanequals_operators) { BOOST_AUTO_TEST_CASE(float_greaterthan_operators) { // Test basic greater-than functionality - fp_compare_epsilon alpha = fp_compare_epsilon(98325.4); - fp_compare_epsilon beta = fp_compare_epsilon(alpha._value + 0.15); + fp_compare_epsilon alpha = fp_compare_epsilon(98325.4f); + fp_compare_epsilon beta = fp_compare_epsilon(alpha._value + 0.15f); BOOST_CHECK(beta > alpha); BOOST_CHECK(float(alpha._value + 0.15) > alpha); // Test false greater-than case - fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value + 1.2); + fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value + 1.2f); BOOST_CHECK(not (alpha > charlie)); - BOOST_CHECK(not (alpha > float(alpha._value + 1.2))); + BOOST_CHECK(not (alpha > float(alpha._value + 1.2f))); } BOOST_AUTO_TEST_CASE(double_greaterthan_operators) { @@ -209,17 +209,17 @@ BOOST_AUTO_TEST_CASE(double_greaterthan_operators) { BOOST_AUTO_TEST_CASE(float_greaterthanequals_operators) { // Test that >= correctly reports for equal values - fp_compare_epsilon alpha = fp_compare_epsilon(7834.89); + fp_compare_epsilon alpha = fp_compare_epsilon(7834.89f); fp_compare_epsilon beta = fp_compare_epsilon(alpha._value); BOOST_CHECK(alpha >= beta); BOOST_CHECK(alpha >= float(alpha._value)); // Test that >= correctly reports for greater-than values - fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value + 4.8); + fp_compare_epsilon charlie = fp_compare_epsilon(alpha._value + 4.8f); BOOST_CHECK(charlie >= alpha); - BOOST_CHECK(float(alpha._value + 4.8) >= alpha); + BOOST_CHECK(float(alpha._value + 4.8f) >= alpha); } BOOST_AUTO_TEST_CASE(double_greaterthanequals_operators) { diff --git a/host/utils/usrp_cal_utils.hpp b/host/utils/usrp_cal_utils.hpp index c027a4785..ccdb0a61d 100644 --- a/host/utils/usrp_cal_utils.hpp +++ b/host/utils/usrp_cal_utils.hpp @@ -249,7 +249,7 @@ static void capture_samples( // Right after the stream is started, there will be transient data. // That transient data is discarded and only "good" samples are returned. - size_t nsamps_to_discard = usrp->get_rx_rate() * 0.001; // 1ms to be discarded + size_t nsamps_to_discard = size_t(usrp->get_rx_rate() * 0.001); // 1ms to be discarded std::vector discard_buff(nsamps_to_discard); uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); -- cgit v1.2.3 From d1ca5a10a1c79092ca5b20f52989d6e8b81306c0 Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Thu, 12 Mar 2015 10:43:13 -0700 Subject: e300: Fix missing namespace prefixes. In several files we were lacking boost:: namespace prefixes, which led to build failures on certain configurations. Signed-off-by: Moritz Fischer --- host/lib/usrp/e300/e300_eeprom_manager.cpp | 4 ++-- host/lib/usrp/e300/e300_sensor_manager.hpp | 2 +- host/lib/usrp/e300/e300_spi.cpp | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_eeprom_manager.cpp b/host/lib/usrp/e300/e300_eeprom_manager.cpp index dad6741f5..778e3150c 100644 --- a/host/lib/usrp/e300/e300_eeprom_manager.cpp +++ b/host/lib/usrp/e300/e300_eeprom_manager.cpp @@ -21,7 +21,7 @@ namespace uhd { namespace usrp { namespace e300 { -static const std::string _bytes_to_string(const uint8_t* bytes, size_t max_len) +static const std::string _bytes_to_string(const boost::uint8_t* bytes, size_t max_len) { std::string out; for (size_t i = 0; i < max_len; i++) { @@ -31,7 +31,7 @@ static const std::string _bytes_to_string(const uint8_t* bytes, size_t max_len) return out; } -static void _string_to_bytes(const std::string &string, size_t max_len, uint8_t* buffer) +static void _string_to_bytes(const std::string &string, size_t max_len, boost::uint8_t* buffer) { byte_vector_t bytes; const size_t len = std::min(string.size(), max_len); diff --git a/host/lib/usrp/e300/e300_sensor_manager.hpp b/host/lib/usrp/e300/e300_sensor_manager.hpp index 9c060b19a..09f889251 100644 --- a/host/lib/usrp/e300/e300_sensor_manager.hpp +++ b/host/lib/usrp/e300/e300_sensor_manager.hpp @@ -62,7 +62,7 @@ public: // Note: This is a hack static boost::uint32_t pack_float_in_uint32_t(const float &v) { - const boost::uint32_t *cast = reinterpret_cast(&v); + const boost::uint32_t *cast = reinterpret_cast(&v); return *cast; } diff --git a/host/lib/usrp/e300/e300_spi.cpp b/host/lib/usrp/e300/e300_spi.cpp index 9a2daf4a7..2722d7f53 100644 --- a/host/lib/usrp/e300/e300_spi.cpp +++ b/host/lib/usrp/e300/e300_spi.cpp @@ -82,13 +82,13 @@ public: int ret(0); struct spi_ioc_transfer tr; - uint8_t *tx_data = reinterpret_cast(&data); + boost::uint8_t *tx_data = reinterpret_cast(&data); UHD_ASSERT_THROW(num_bits == 24); - uint8_t tx[] = {tx_data[2], tx_data[1], tx_data[0]}; + boost::uint8_t tx[] = {tx_data[2], tx_data[1], tx_data[0]}; - uint8_t rx[3]; + boost::uint8_t rx[3]; tr.tx_buf = (unsigned long) &tx[0]; tr.rx_buf = (unsigned long) &rx[0]; tr.len = num_bits >> 3; -- cgit v1.2.3 From 306b5243e12af0db493856ad8397abac9835db0c Mon Sep 17 00:00:00 2001 From: Julian Arnold Date: Thu, 12 Mar 2015 10:19:08 -0700 Subject: ad9361: DC and IQ correction only done if df > 100MHz during a tune request --- host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 19 +++++++++++++------ host/lib/usrp/common/ad9361_driver/ad9361_device.h | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index ba66769dd..92ad0ee3f 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -80,6 +80,7 @@ int get_num_taps(int max_num_taps) { const double ad9361_device_t::AD9361_MAX_GAIN = 89.75; const double ad9361_device_t::AD9361_MAX_CLOCK_RATE = 61.44e6; const double ad9361_device_t::AD9361_RECOMMENDED_MAX_CLOCK_RATE = 56e6; +const double ad9361_device_t::AD9361_CAL_VALID_WINDOW = 100e6; /* Program either the RX or TX FIR filter. * @@ -1455,6 +1456,7 @@ void ad9361_device_t::initialize() _rx2_agc_mode = GAIN_MODE_SLOW_AGC; _rx1_agc_enable = false; _rx2_agc_enable = false; + _last_calibration_freq = -AD9361_CAL_VALID_WINDOW; /* Reset the device. */ _io_iface->poke8(0x000, 0x01); @@ -1890,12 +1892,17 @@ double ad9361_device_t::tune(direction_t direction, const double value) /* Update the gain settings. */ _reprogram_gains(); - /* Run the calibration algorithms. */ - _calibrate_baseband_dc_offset(); - _calibrate_rf_dc_offset(); - _calibrate_tx_quadrature(); - _calibrate_rx_quadrature(); - _configure_bb_rf_dc_tracking(_use_dc_offset_correction); //if this is not done here, bb dc offset is not good + /* Only run the following calibrations if we are more than 100MHz away + * from the previous calibration point. */ + if (std::abs(_last_calibration_freq - tune_freq) > AD9361_CAL_VALID_WINDOW) { + /* Run the calibration algorithms. */ + _calibrate_rf_dc_offset(); + _calibrate_tx_quadrature(); + _calibrate_rx_quadrature(); + _configure_bb_rf_dc_tracking(_use_dc_offset_correction); + _last_calibration_freq = tune_freq; + } + /* If we were in the FDD state, return it now. */ if (not_in_alert) { _io_iface->poke8(0x014, 0x21); diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index 1cfff9971..7c53ff0c4 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -89,6 +89,7 @@ public: static const double AD9361_MAX_GAIN; static const double AD9361_MAX_CLOCK_RATE; static const double AD9361_RECOMMENDED_MAX_CLOCK_RATE; + static const double AD9361_CAL_VALID_WINDOW; private: //Methods void _program_fir_filter(direction_t direction, int num_taps, boost::uint16_t *coeffs); @@ -134,6 +135,7 @@ private: //Members ad9361_io::sptr _io_iface; //Intermediate state double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq; + double _last_calibration_freq; double _baseband_bw, _bbpll_freq, _adcclock_freq; double _req_clock_rate, _req_coreclk; boost::uint16_t _rx_bbf_tunediv; -- cgit v1.2.3