1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
//
// Copyright 2013 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// Original ADF4001 driver written by: bistromath
// Mar 1, 2013
//
// Re-used and re-licensed with permission.
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/utils/log.hpp>
#include <uhdlib/usrp/common/adf4001_ctrl.hpp>
#include <iomanip>
#include <iostream>
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;
}
uint32_t adf4001_regs_t::get_reg(uint8_t addr)
{
uint32_t reg = 0;
switch (addr) {
case 0:
reg |= (uint32_t(ref_counter) & 0x003FFF) << 2;
reg |= (uint32_t(anti_backlash_width) & 0x000003) << 16;
reg |= (uint32_t(lock_detect_precision) & 0x000001) << 20;
break;
case 1:
reg |= (uint32_t(n) & 0x001FFF) << 8;
reg |= (uint32_t(charge_pump_gain) & 0x000001) << 21;
break;
case 2:
reg |= (uint32_t(counter_reset) & 0x000001) << 2;
reg |= (uint32_t(power_down) & 0x000001) << 3;
reg |= (uint32_t(muxout) & 0x000007) << 4;
reg |= (uint32_t(phase_detector_polarity) & 0x000001) << 7;
reg |= (uint32_t(charge_pump_mode) & 0x000001) << 8;
reg |= (uint32_t(fastlock_mode) & 0x000003) << 9;
reg |= (uint32_t(timer_counter_control) & 0x00000F) << 11;
reg |= (uint32_t(charge_pump_current_1) & 0x000007) << 15;
reg |= (uint32_t(charge_pump_current_2) & 0x000007) << 18;
reg |= (uint32_t(power_down) & 0x000002) << 20;
break;
case 3:
reg |= (uint32_t(counter_reset) & 0x000001) << 2;
reg |= (uint32_t(power_down) & 0x000001) << 3;
reg |= (uint32_t(muxout) & 0x000007) << 4;
reg |= (uint32_t(phase_detector_polarity) & 0x000001) << 7;
reg |= (uint32_t(charge_pump_mode) & 0x000001) << 8;
reg |= (uint32_t(fastlock_mode) & 0x000003) << 9;
reg |= (uint32_t(timer_counter_control) & 0x00000F) << 11;
reg |= (uint32_t(charge_pump_current_1) & 0x000007) << 15;
reg |= (uint32_t(charge_pump_current_2) & 0x000007) << 18;
reg |= (uint32_t(power_down) & 0x000002) << 20;
break;
default:
break;
}
reg |= (uint32_t(addr) & 0x03);
return reg;
}
adf4001_ctrl::adf4001_ctrl(uhd::spi_iface::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);
// conduct a function latch (2)
write_reg(2);
// write R counter latch (0)
write_reg(0);
// write N counter latch (1)
write_reg(1);
}
void adf4001_ctrl::write_reg(uint8_t addr)
{
uint32_t reg = adf4001_regs.get_reg(addr); // load the reg data
spi_iface->transact_spi(slaveno, spi_config, reg, 24, false);
}
|