aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/common/adf4001_ctrl.cpp
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2013-07-19 14:00:32 -0700
committerJosh Blum <josh@joshknows.com>2013-07-19 14:00:32 -0700
commitbb73a21495e15b6221472cb1838b609a91f9c59c (patch)
treee80469363084a6262ff6403edd23ee0b48ff0aba /host/lib/usrp/common/adf4001_ctrl.cpp
parent7c9a4a5a41bb981dd4db66e7b479e4e66d488fa5 (diff)
downloaduhd-bb73a21495e15b6221472cb1838b609a91f9c59c.tar.gz
uhd-bb73a21495e15b6221472cb1838b609a91f9c59c.tar.bz2
uhd-bb73a21495e15b6221472cb1838b609a91f9c59c.zip
uhd: squashed support modules for usrp3 fpga cores
Diffstat (limited to 'host/lib/usrp/common/adf4001_ctrl.cpp')
-rw-r--r--host/lib/usrp/common/adf4001_ctrl.cpp151
1 files changed, 151 insertions, 0 deletions
diff --git a/host/lib/usrp/common/adf4001_ctrl.cpp b/host/lib/usrp/common/adf4001_ctrl.cpp
new file mode 100644
index 000000000..46171c7ce
--- /dev/null
+++ b/host/lib/usrp/common/adf4001_ctrl.cpp
@@ -0,0 +1,151 @@
+//
+// Copyright 2013 Ettus Research LLC
+//
+// Original ADF4001 driver written by: bistromath
+// Mar 1, 2013
+//
+// Re-used and re-licensed with permission.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#include "adf4001_ctrl.hpp"
+
+#include <uhd/utils/msg.hpp>
+#include <iostream>
+#include <iomanip>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+adf4001_regs_t::adf4001_regs_t(void) {
+ ref_counter = 0;
+ n = 0;
+ charge_pump_current_1 = 0;
+ charge_pump_current_2 = 0;
+ anti_backlash_width = ANTI_BACKLASH_WIDTH_2_9NS;
+ lock_detect_precision = LOCK_DETECT_PRECISION_3CYC;
+ charge_pump_gain = CHARGE_PUMP_GAIN_1;
+ counter_reset = COUNTER_RESET_NORMAL;
+ power_down = POWER_DOWN_NORMAL;
+ muxout = MUXOUT_TRISTATE_OUT;
+ phase_detector_polarity = PHASE_DETECTOR_POLARITY_NEGATIVE;
+ charge_pump_mode = CHARGE_PUMP_TRISTATE;
+ fastlock_mode = FASTLOCK_MODE_DISABLED;
+ timer_counter_control = TIMEOUT_3CYC;
+}
+
+
+boost::uint32_t adf4001_regs_t::get_reg(boost::uint8_t addr) {
+ boost::uint32_t reg = 0;
+ switch (addr) {
+ case 0:
+ reg |= (boost::uint32_t(ref_counter) & 0x003FFF) << 2;
+ reg |= (boost::uint32_t(anti_backlash_width) & 0x000003) << 16;
+ reg |= (boost::uint32_t(lock_detect_precision) & 0x000001) << 20;
+ break;
+ case 1:
+ reg |= (boost::uint32_t(n) & 0x001FFF) << 8;
+ reg |= (boost::uint32_t(charge_pump_gain) & 0x000001) << 21;
+ break;
+ case 2:
+ reg |= (boost::uint32_t(counter_reset) & 0x000001) << 2;
+ reg |= (boost::uint32_t(power_down) & 0x000001) << 3;
+ reg |= (boost::uint32_t(muxout) & 0x000007) << 4;
+ reg |= (boost::uint32_t(phase_detector_polarity) & 0x000001) << 7;
+ reg |= (boost::uint32_t(charge_pump_mode) & 0x000001) << 8;
+ reg |= (boost::uint32_t(fastlock_mode) & 0x000003) << 9;
+ reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11;
+ reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15;
+ reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18;
+ reg |= (boost::uint32_t(power_down) & 0x000002) << 21;
+ break;
+ case 3:
+ reg |= (boost::uint32_t(counter_reset) & 0x000001) << 2;
+ reg |= (boost::uint32_t(power_down) & 0x000001) << 3;
+ reg |= (boost::uint32_t(muxout) & 0x000007) << 4;
+ reg |= (boost::uint32_t(phase_detector_polarity) & 0x000001) << 7;
+ reg |= (boost::uint32_t(charge_pump_mode) & 0x000001) << 8;
+ reg |= (boost::uint32_t(fastlock_mode) & 0x000003) << 9;
+ reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11;
+ reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15;
+ reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18;
+ reg |= (boost::uint32_t(power_down) & 0x000002) << 21;
+ break;
+ default:
+ break;
+ }
+
+ reg |= (boost::uint32_t(addr) & 0x03);
+
+ return reg;
+}
+
+
+adf4001_ctrl::adf4001_ctrl(spi_core_3000::sptr _spi, int slaveno):
+ spi_iface(_spi),
+ slaveno(slaveno)
+ {
+
+ spi_config.mosi_edge = spi_config_t::EDGE_RISE;
+
+ //set defaults
+ adf4001_regs.ref_counter = 1;
+ adf4001_regs.n = 4;
+ adf4001_regs.charge_pump_current_1 = 7;
+ adf4001_regs.charge_pump_current_2 = 7;
+ adf4001_regs.muxout = adf4001_regs_t::MUXOUT_DLD;
+ adf4001_regs.counter_reset = adf4001_regs_t::COUNTER_RESET_NORMAL;
+ adf4001_regs.phase_detector_polarity = adf4001_regs_t::PHASE_DETECTOR_POLARITY_POSITIVE;
+ adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_TRISTATE;
+
+ //everything else should be defaults
+
+ program_regs();
+}
+
+void adf4001_ctrl::set_lock_to_ext_ref(bool external) {
+ if(external) {
+ adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_NORMAL;
+ } else {
+ adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_TRISTATE;
+ }
+
+ program_regs();
+}
+
+void adf4001_ctrl::program_regs(void) {
+ //no control over CE, only LE, therefore we use the initialization latch method
+ write_reg(3);
+ boost::this_thread::sleep(boost::posix_time::microseconds(1));
+
+ //write R counter latch (0)
+ write_reg(0);
+ boost::this_thread::sleep(boost::posix_time::microseconds(1));
+
+ //write N counter latch (1)
+ write_reg(1);
+ boost::this_thread::sleep(boost::posix_time::microseconds(1));
+}
+
+
+void adf4001_ctrl::write_reg(boost::uint8_t addr) {
+ boost::uint32_t reg = adf4001_regs.get_reg(addr); //load the reg data
+
+ spi_iface->transact_spi(slaveno,
+ spi_config,
+ reg,
+ 24,
+ false);
+}