From adb6a061687d470b6f6ccdb3221855808396cd39 Mon Sep 17 00:00:00 2001 From: Tom Tsou Date: Thu, 30 Apr 2015 20:39:34 -0700 Subject: convert: Add sc16-sc16 SSE converter The sc16-sc16 wire to host type converter is effectively an I/Q swap or 16-bit byteswap for little and big endian cases respectively. This implmentation is a subset of fc32 and fc64 converters without the floating point portion and scaling. The resulting byte ordering is as follows: ----------------- | A | B | C | D | Wire ----------------- 0 1 2 3 ----------------- | C | D | A | B | Litte-endian ----------------- 0 1 2 3 ----------------- | B | A | D | C | Big-endian ----------------- 0 1 2 3 Signed-off-by: Tom Tsou --- host/lib/convert/CMakeLists.txt | 1 + host/lib/convert/sse2_sc16_to_sc16.cpp | 201 +++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+) create mode 100644 host/lib/convert/sse2_sc16_to_sc16.cpp (limited to 'host/lib') diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt index bec88b520..5204c29ea 100644 --- a/host/lib/convert/CMakeLists.txt +++ b/host/lib/convert/CMakeLists.txt @@ -70,6 +70,7 @@ SET(CMAKE_REQUIRED_FLAGS) IF(HAVE_EMMINTRIN_H) SET(convert_with_sse2_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sse2_sc16_to_sc16.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sse2_sc16_to_fc64.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sse2_sc16_to_fc32.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sse2_sc8_to_fc64.cpp diff --git a/host/lib/convert/sse2_sc16_to_sc16.cpp b/host/lib/convert/sse2_sc16_to_sc16.cpp new file mode 100644 index 000000000..85195c9c0 --- /dev/null +++ b/host/lib/convert/sse2_sc16_to_sc16.cpp @@ -0,0 +1,201 @@ +// +// 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 "convert_common.hpp" +#include +#include + +using namespace uhd::convert; + +// +// SSE 16-bit pair swap +// +// Valid alignment macro arguments are 'u_' and '_' for unaligned and aligned +// access respectively. Macro operates on 4 complex 16-bit integers at a time. +// +// ----------------- +// | A | B | C | D | Input +// ----------------- +// 0 1 2 3 Address +// ----------------- +// | C | D | A | B | Output +// ----------------- +// +#define CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(_ialign_,_oalign_) \ + for (; i+3 < nsamps; i+=4) { \ + __m128i m0; \ + \ + /* load from input */ \ + m0 = _mm_load ## _ialign_ ## si128((const __m128i *) (input+i));\ + \ + /* swap 16-bit pairs */ \ + m0 = _mm_shufflelo_epi16(m0, _MM_SHUFFLE(2, 3, 0, 1)); \ + m0 = _mm_shufflehi_epi16(m0, _MM_SHUFFLE(2, 3, 0, 1)); \ + \ + /* store to output */ \ + _mm_store ## _oalign_ ## si128((__m128i *) (output+i), m0); \ + } \ + +// +// SSE byte swap +// +// Valid alignment macro arguments are 'u_' and '_' for unaligned and aligned +// access respectively. Macro operates on 4 complex 16-bit integers at a time. +// +// ----------------- +// | A | B | C | D | Input +// ----------------- +// 0 1 2 3 Address +// ----------------- +// | B | A | D | C | Output +// ----------------- +// +#define CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(_ialign_,_oalign_) \ + for (; i+3 < nsamps; i+=4) { \ + __m128i m0, m1, m2; \ + \ + /* load from input */ \ + m0 = _mm_load ## _ialign_ ## si128((const __m128i *) (input+i));\ + \ + /* byteswap 16 bit words */ \ + m1 = _mm_srli_epi16(m0, 8); \ + m2 = _mm_slli_epi16(m0, 8); \ + m0 = _mm_or_si128(m1, m2); \ + \ + /* store to output */ \ + _mm_store ## _oalign_ ## si128((__m128i *) (output+i), m0); \ + } \ + +DECLARE_CONVERTER(sc16, 1, sc16_item32_le, 1, PRIORITY_SIMD){ + const sc16_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + size_t i = 0; + + // need to dispatch according to alignment for fastest conversion + switch (size_t(input) & 0xf){ + case 0x0: + // the data is 16-byte aligned, so do the fast processing of the bulk of the samples + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(_,u_) + break; + case 0x8: + if (nsamps < 2) + break; + // the first sample is 8-byte aligned - process it to align the remainder of the samples to 16-bytes + xx_to_item32_sc16(input, output, 2, 1.0); + i += 2; + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(_,u_) + // do faster processing of the bulk of the samples now that we are 16-byte aligned + break; + default: + // we are not 8 or 16-byte aligned, so do fast processing with the unaligned load + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(u_,u_) + } + + // convert any remaining samples + xx_to_item32_sc16(input+i, output+i, nsamps-i, 1.0); +} + +DECLARE_CONVERTER(sc16, 1, sc16_item32_be, 1, PRIORITY_SIMD){ + const sc16_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + size_t i = 0; + + // need to dispatch according to alignment for fastest conversion + switch (size_t(input) & 0xf){ + case 0x0: + // the data is 16-byte aligned, so do the fast processing of the bulk of the samples + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(_,u_) + break; + case 0x8: + if (nsamps < 2) + break; + // the first value is 8-byte aligned - process it and prepare the bulk of the data for fast conversion + xx_to_item32_sc16(input, output, 2, 1.0); + i += 2; + // do faster processing of the remaining samples now that we are 16-byte aligned + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(_,u_) + break; + default: + // we are not 8 or 16-byte aligned, so do fast processing with the unaligned load + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(u_,u_) + } + + // convert any remaining samples + xx_to_item32_sc16(input+i, output+i, nsamps-i, 1.0); +} + +DECLARE_CONVERTER(sc16_item32_le, 1, sc16, 1, PRIORITY_SIMD){ + const item32_t *input = reinterpret_cast(inputs[0]); + sc16_t *output = reinterpret_cast(outputs[0]); + + size_t i = 0; + + // need to dispatch according to alignment for fastest conversion + switch (size_t(output) & 0xf){ + case 0x0: + // the data is 16-byte aligned, so do the fast processing of the bulk of the samples + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(u_,_) + break; + case 0x8: + if (nsamps < 2) + break; + // the first sample is 8-byte aligned - process it to align the remainder of the samples to 16-bytes + item32_sc16_to_xx(input, output, 2, 1.0); + i += 2; + // do faster processing of the bulk of the samples now that we are 16-byte aligned + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(u_,_) + break; + default: + // we are not 8 or 16-byte aligned, so do fast processing with the unaligned load and store + CONVERT_SC16_1_TO_SC16_1_NSWAP_GUTS(u_,u_) + } + + // convert any remaining samples + item32_sc16_to_xx(input+i, output+i, nsamps-i, 1.0); +} + +DECLARE_CONVERTER(sc16_item32_be, 1, sc16, 1, PRIORITY_SIMD){ + const item32_t *input = reinterpret_cast(inputs[0]); + sc16_t *output = reinterpret_cast(outputs[0]); + + size_t i = 0; + + // need to dispatch according to alignment for fastest conversion + switch (size_t(output) & 0xf){ + case 0x0: + // the data is 16-byte aligned, so do the fast processing of the bulk of the samples + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(u_,_) + break; + case 0x8: + if (nsamps < 2) + break; + // the first sample is 8-byte aligned - process it to align the remainder of the samples to 16-bytes + item32_sc16_to_xx(input, output, 2, 1.0); + i += 2; + // do faster processing of the bulk of the samples now that we are 16-byte aligned + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(u_,_) + break; + default: + // we are not 8 or 16-byte aligned, so do fast processing with the unaligned load and store + CONVERT_SC16_1_TO_SC16_1_BSWAP_GUTS(u_,u_) + } + + // convert any remaining samples + item32_sc16_to_xx(input+i, output+i, nsamps-i, 1.0); +} -- cgit v1.2.3 From 2fc2fb36eb09fd03c0c95393e896baa9cdb47d2d Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 12 May 2015 15:49:22 -0700 Subject: fixup! e300: gps: If gps is detected, set device time to gps time on init. Signed-off-by: Moritz Fischer --- host/lib/usrp/e300/e300_impl.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index b35bbab4e..693aa5734 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -578,6 +578,9 @@ e300_impl::e300_impl(const uhd::device_addr_t &device_addr) UHD_MSG(status) << "Initializing time to the internal GPSDO" << std::endl; const time_t tp = time_t(_sensor_manager->get_sensor("gps_time").to_int()+1); _tree->access(mb_path / "time" / "pps").set(time_spec_t(tp)); + + // wait for time to be actually set + boost::this_thread::sleep(boost::posix_time::seconds(1)); } boost::uint8_t e300_impl::_get_internal_gpio( -- cgit v1.2.3 From adac03ceb88dc9d11f9bc29afbbd49c4981c48ea Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Tue, 19 May 2015 13:44:21 -0700 Subject: ad9361: Minor clarifications on req_rate and baseband_bw --- host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 6 ++++-- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 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 e3139cd39..413ec75a2 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1247,7 +1247,7 @@ double ad9361_device_t::_setup_rates(const double rate) /* If we make it into this function, then we are tuning to a new rate. * Store the new rate. */ _req_clock_rate = rate; - UHD_LOG << boost::format("[ad9361_device_t::_setup_rates] rate=%d\n") % rate; + UHD_LOG << boost::format("[ad9361_device_t::_setup_rates] rate=%.6d\n") % rate; /* Set the decimation and interpolation values in the RX and TX chains. * This also switches filters in / out. Note that all transmitters and @@ -1629,7 +1629,9 @@ double ad9361_device_t::set_clock_rate(const double req_rate) * starts up. This prevents that, and any bugs in user code that request * the same rate over and over. */ if (freq_is_nearly_equal(req_rate, _req_clock_rate)) { - return _baseband_bw; // IJB. Should this not return req_rate? + // We return _baseband_bw, because that's closest to the + // actual value we're currently running. + return _baseband_bw; } /* We must be in the SLEEP / WAIT state to do this. If we aren't already diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index bd4ad368f..a42c5ac9a 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -112,8 +112,15 @@ private: //Members ad9361_io::sptr _io_iface; //Intermediate state double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq; - double _baseband_bw, _bbpll_freq, _adcclock_freq; - double _req_clock_rate, _req_coreclk; + //! Current baseband sampling rate (this is the actual rate the device is + // is running at) + double _baseband_bw; + double _bbpll_freq, _adcclock_freq; + //! This was the last clock rate value that was requested. + // It is cached so we don't need to re-set the clock rate + // if another call to set_clock_rate() actually has the same value. + double _req_clock_rate; + double _req_coreclk; boost::uint16_t _rx_bbf_tunediv; boost::uint8_t _curr_gain_table; double _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain; -- cgit v1.2.3 From c9af74e569d0d61a008f5bf0257c860b2b473381 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 18 May 2015 12:13:18 -0700 Subject: x300: Updated clock rate / ref freq warnings for clarity --- host/lib/usrp/x300/x300_clock_ctrl.cpp | 44 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 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 9bea4a4b4..6450686dd 100644 --- a/host/lib/usrp/x300/x300_clock_ctrl.cpp +++ b/host/lib/usrp/x300/x300_clock_ctrl.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 @@ -18,6 +18,7 @@ #include "lmk04816_regs.hpp" #include "x300_clock_ctrl.hpp" #include +#include #include #include #include @@ -96,7 +97,7 @@ public: boost::uint8_t addr = 0xFF; // Make sure requested rate is an even divisor of the VCO frequency - if (not doubles_are_equal(_vco_freq / div, rate)) + if (not math::frequencies_are_equal(_vco_freq / div, rate)) throw uhd::value_error("invalid dboard rate requested"); switch (which) @@ -236,27 +237,42 @@ private: * clock, in zero-delay mode. */ opmode_t clocking_mode = INVALID; - if(doubles_are_equal(_system_ref_rate, 10e6)) { - if(doubles_are_equal(_master_clock_rate, 184.32e6)) { + if (math::frequencies_are_equal(_system_ref_rate, 10e6)) { + if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 10MHz reference, 184.32 MHz master clock out, NOT Zero Delay. */ clocking_mode = m10M_184_32M_NOZDEL; - } else if(doubles_are_equal(_master_clock_rate, 200e6)) { + } else if (math::frequencies_are_equal(_master_clock_rate, 200e6)) { /* 10MHz reference, 200 MHz master clock out, Zero Delay */ clocking_mode = m10M_200M_ZDEL; - } else if(doubles_are_equal(_master_clock_rate, 120e6)) { + } else if (math::frequencies_are_equal(_master_clock_rate, 120e6)) { /* 10MHz reference, 120 MHz master clock rate, Zero Delay */ clocking_mode = m10M_120M_ZDEL; + } else { + throw uhd::runtime_error(str( + boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rates when using a %f MHz reference clock are:\n" + "120 MHz, 184.32 MHz and 200 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) + )); } - } else if(doubles_are_equal(_system_ref_rate, 30.72e6)) { - if(doubles_are_equal(_master_clock_rate, 184.32e6)) { + } else if (math::frequencies_are_equal(_system_ref_rate, 30.72e6)) { + if (math::frequencies_are_equal(_master_clock_rate, 184.32e6)) { /* 30.72MHz reference, 184.32 MHz master clock out, Zero Delay */ clocking_mode = m30_72M_184_32M_ZDEL; + } else { + throw uhd::runtime_error(str( + boost::format("Invalid master clock rate: %.2f MHz.\n" + "Valid master clock rate when using a %.2f MHz reference clock is: 184.32 MHz.") + % (_master_clock_rate / 1e6) % (_system_ref_rate / 1e6) + )); } + } else { + throw uhd::runtime_error(str( + boost::format("Invalid system reference rate: %.2f MHz.\nValid reference frequencies are: 10 MHz, 30.72 MHz.") + % (_system_ref_rate / 1e6) + )); } - - if(clocking_mode == INVALID) { - throw uhd::runtime_error(str(boost::format("A master clock rate of %f cannot be derived from a system reference rate of %f") % _master_clock_rate % _system_ref_rate)); - } + UHD_ASSERT_THROW(clocking_mode != INVALID); // For 200 MHz output, the VCO is run at 2400 MHz // For the LTE/CPRI rate of 184.32 MHz, the VCO runs at 2580.48 MHz @@ -496,10 +512,6 @@ private: this->sync_clocks(); } - UHD_INLINE bool doubles_are_equal(double a, double b) { - return (std::fabs(a - b) < std::numeric_limits::epsilon()); - } - const spi_iface::sptr _spiface; const size_t _slaveno; const size_t _hw_rev; -- cgit v1.2.3 From da7302cacbcdad59df01a7d7789db3c6fa9c6b24 Mon Sep 17 00:00:00 2001 From: michael-west Date: Fri, 15 May 2015 17:06:51 -0700 Subject: B200/E300: Fix incorrect readback of frequency. When the LO is tuned it changes the frequency on both channels. The frequency value read back for the first channel was not updated when the LO frequency for the other channel was tuned to a different value. --- host/lib/usrp/b200/b200_impl.cpp | 1 + host/lib/usrp/common/ad9361_ctrl.cpp | 9 +++++++++ host/lib/usrp/common/ad9361_ctrl.hpp | 3 +++ host/lib/usrp/common/ad9361_driver/ad9361_device.cpp | 17 ++++++++++++++--- host/lib/usrp/common/ad9361_driver/ad9361_device.h | 3 +++ host/lib/usrp/e300/e300_impl.cpp | 1 + 6 files changed, 31 insertions(+), 3 deletions(-) (limited to 'host/lib') diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp index bd07fcaee..bac904a31 100644 --- a/host/lib/usrp/b200/b200_impl.cpp +++ b/host/lib/usrp/b200/b200_impl.cpp @@ -684,6 +684,7 @@ void b200_impl::setup_radio(const size_t dspno) _tree->create(rf_fe_path / "bandwidth" / "range") .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key)); _tree->create(rf_fe_path / "freq" / "value") + .publish(boost::bind(&ad9361_ctrl::get_freq, _codec_ctrl, key)) .coerce(boost::bind(&ad9361_ctrl::tune, _codec_ctrl, key, _1)) .subscribe(boost::bind(&b200_impl::update_bandsel, this, key, _1)) .set(B200_DEFAULT_FREQ); diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp index bedd2eb32..65e8e2df9 100644 --- a/host/lib/usrp/common/ad9361_ctrl.cpp +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -149,6 +149,15 @@ public: return _device.tune(direction, value); } + //! get the current frequency for the given frontend + double get_freq(const std::string &which) + { + boost::lock_guard lock(_mutex); + + ad9361_device_t::direction_t direction = _get_direction_from_antenna(which); + return _device.get_freq(direction); + } + //! turn on/off data port loopback void data_port_loopback(const bool on) { diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp index c5718302f..b7d7b8e26 100644 --- a/host/lib/usrp/common/ad9361_ctrl.hpp +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -95,6 +95,9 @@ public: //! tune the given frontend, return the exact value virtual double tune(const std::string &which, const double value) = 0; + //! get the current frequency for the given frontend + virtual double get_freq(const std::string &which) = 0; + //! turn on/off data port loopback virtual void data_port_loopback(const bool on) = 0; diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp index 413ec75a2..e63460730 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp @@ -1050,7 +1050,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++) { @@ -1855,10 +1855,21 @@ double ad9361_device_t::tune(direction_t direction, const double value) return tune_freq; } +/* Get the current RX or TX frequency. */ +double ad9361_device_t::get_freq(direction_t direction) +{ + boost::lock_guard lock(_mutex); + + if (direction == RX) + return _rx_freq; + else + return _tx_freq; +} + /* Set the gain of RX1, RX2, TX1, or TX2. * - * Note that the 'value' passed to this function is the gain index - * for RX. Also note that the RX chains are done in terms of gain, and + * Note that the 'value' passed to this function is the gain index + * for RX. Also note that the RX chains are done in terms of gain, and * the TX chains are done in terms of attenuation. */ double ad9361_device_t::set_gain(direction_t direction, chain_t chain, const double value) { diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h index a42c5ac9a..71ce78da7 100644 --- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h +++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h @@ -49,6 +49,9 @@ public: * After tuning, it runs any appropriate calibrations. */ double tune(direction_t direction, const double value); + /* Get the current RX or TX frequency. */ + double get_freq(direction_t direction); + /* Set the gain of RX1, RX2, TX1, or TX2. * * Note that the 'value' passed to this function is the actual gain value, diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 693aa5734..41e8eacf3 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -1053,6 +1053,7 @@ void e300_impl::_setup_radio(const size_t dspno) _tree->create(rf_fe_path / "bandwidth" / "range") .publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key)); _tree->create(rf_fe_path / "freq" / "value") + .publish(boost::bind(&ad9361_ctrl::get_freq, _codec_ctrl, key)) .coerce(boost::bind(&ad9361_ctrl::tune, _codec_ctrl, key, _1)) .subscribe(boost::bind(&e300_impl::_update_fe_lo_freq, this, key, _1)) .set(e300::DEFAULT_FE_FREQ); -- cgit v1.2.3 From 6113b921e4cce8fdb57575eb9418b84322d87c3c Mon Sep 17 00:00:00 2001 From: michael-west Date: Tue, 19 May 2015 11:34:57 -0700 Subject: E300: Implement get_freq() for E300 network mode. --- host/lib/usrp/e300/e300_network.cpp | 3 +++ host/lib/usrp/e300/e300_remote_codec_ctrl.cpp | 14 ++++++++++++++ host/lib/usrp/e300/e300_remote_codec_ctrl.hpp | 1 + 3 files changed, 18 insertions(+) (limited to 'host/lib') diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp index bb904773b..408f9e62d 100644 --- a/host/lib/usrp/e300/e300_network.cpp +++ b/host/lib/usrp/e300/e300_network.cpp @@ -220,6 +220,9 @@ static void e300_codec_ctrl_tunnel( case codec_xact_t::ACTION_TUNE: out->freq = _codec_ctrl->tune(which_str, in->freq); break; + case codec_xact_t::ACTION_GET_FREQ: + out->freq = _codec_ctrl->get_freq(which_str); + break; case codec_xact_t::ACTION_SET_LOOPBACK: _codec_ctrl->data_port_loopback( uhd::ntohx(in->bits) & 1); diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp index d3942d587..6742f5f86 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp @@ -96,6 +96,20 @@ public: return _retval.freq; } + double get_freq(const std::string &which) + { + _clear(); + _args.action = uhd::htonx(transaction_t::ACTION_GET_FREQ); + 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."); + + _transact(); + return _retval.freq; + } + void data_port_loopback(const bool on) { _clear(); diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp index cbc4b52d2..e21f2ef95 100644 --- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp +++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp @@ -44,6 +44,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_FREQ = 16; //Values for "which" static const boost::uint32_t CHAIN_NONE = 0; -- cgit v1.2.3