diff options
| -rwxr-xr-x | host/lib/ic_reg_maps/gen_adf4360_regs.py | 6 | ||||
| -rw-r--r-- | host/lib/usrp/dboard/db_rfx.cpp | 88 | 
2 files changed, 81 insertions, 13 deletions
diff --git a/host/lib/ic_reg_maps/gen_adf4360_regs.py b/host/lib/ic_reg_maps/gen_adf4360_regs.py index e7c2c9435..bcad1ffd3 100755 --- a/host/lib/ic_reg_maps/gen_adf4360_regs.py +++ b/host/lib/ic_reg_maps/gen_adf4360_regs.py @@ -37,14 +37,14 @@ REGS_DATA_TMPL="""\  ## address 0  ########################################################################  core_power_level         0[2:3]     0          5ma, 10ma, 15ma, 20ma -counter_reset            0[4]       0          normal, reset +counter_operation        0[4]       0          normal, reset  muxout_control           0[5:7]     0          3state, dld, ndiv, dvdd, rdiv, nchan_od_ld, sdo, dgnd  phase_detector_polarity  0[8]       0          neg, pos -cp_three_state           0[9]       0          normal, 3state +charge_pump_output       0[9]       0          normal, 3state  cp_gain_0                0[10]      0          set1, set2  mute_till_ld             0[11]      0          dis, enb  output_power_level       0[12:13]   0          3_5ma, 5_0ma, 7_5ma, 11_0ma -#set $current_setting_enums = "0_31, 0_62, 0_93, 1_25, 1_56, 1_87, 2_18, 2_50" +#set $current_setting_enums = ', '.join(map(lambda x: x+"ma", "0_31 0_62 0_93 1_25 1_56 1_87 2_18 2_50".split()))  current_setting1         0[14:16]   0          $current_setting_enums  current_setting2         0[17:19]   0          $current_setting_enums  power_down               0[20:21]   0          normal_op=0, async_pd=1, sync_pd=3 diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index c38b006b0..4a5786aa4 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -15,6 +15,8 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +static const bool rfx_debug = true; +  // IO Pin functions  #define POWER_UP     (1 << 7)   // Low enables power supply  #define ANT_SW       (1 << 6)   // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2 @@ -39,6 +41,7 @@  #include <uhd/usrp/dboard_manager.hpp>  #include <boost/assign/list_of.hpp>  #include <boost/format.hpp> +#include <boost/math/special_functions/round.hpp>  using namespace uhd;  using namespace uhd::usrp; @@ -215,25 +218,85 @@ double rfx_xcvr::set_lo_freq(      dboard_iface::unit_t unit,      double target_freq  ){ +    if (rfx_debug) std::cerr << boost::format( +        "RFX tune: target frequency %f Mhz" +    ) % (target_freq/100e6) << std::endl; +      //clip the input      target_freq = std::clip(target_freq, _freq_range.min, _freq_range.max); +    if (_div2[unit]) target_freq *= 2; -    //load the registers -    adf4360_regs_t regs; +    //map prescalers to the register enums +    static const uhd::dict<int, adf4360_regs_t::prescaler_value_t> prescaler_to_enum = map_list_of +        (8,  adf4360_regs_t::PRESCALER_VALUE_8_9) +        (16, adf4360_regs_t::PRESCALER_VALUE_16_17) +        (32, adf4360_regs_t::PRESCALER_VALUE_32_33) +    ; -    if (_div2[unit]) target_freq *= 2; -    regs.divide_by_2_output = (_div2[unit])? -        adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 : -        adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ; +    //calculate the following values +    // fvco = [P*B + A] * fref/R +    // fvco*R/fref = P*B + A = N +    int A, B, P, R; double N; +    static const int +        B_min = 3, B_max = 8191, +        A_min = 0, A_max = 31, +        P_min = 8, P_max = 32; +    static const int +        N_min = P_min*B_min + A_min, +        N_max = P_max*B_max + A_max; +    double ref_freq = this->get_iface()->get_clock_rate(unit); +    double ratio = target_freq/ref_freq; + +    for(R = 1; R < 11; R++){ +        //increment R and see if this allows for a large enough N +        N = ratio*R; +        if (N < N_min) continue; +        N = std::clip<double>(N, N_min, N_max); +        break; +    } -    //TODO +    //discover the best value for P, B, and A +    BOOST_FOREACH(P, prescaler_to_enum.keys()){ +        B = int(std::floor(N/P)); +        if (B > B_max) continue; +        B = std::clip(B, B_min, B_max); +        A = boost::math::iround(N - P*B); +        A = std::clip(A, A_min, A_max); +        break; +    } +    //load the register values +    adf4360_regs_t regs; +    regs.core_power_level        = adf4360_regs_t::CORE_POWER_LEVEL_10MA; +    regs.counter_operation       = adf4360_regs_t::COUNTER_OPERATION_NORMAL; +    regs.muxout_control          = adf4360_regs_t::MUXOUT_CONTROL_DLD; +    regs.phase_detector_polarity = adf4360_regs_t::PHASE_DETECTOR_POLARITY_POS; +    regs.charge_pump_output      = adf4360_regs_t::CHARGE_PUMP_OUTPUT_NORMAL; +    regs.cp_gain_0               = adf4360_regs_t::CP_GAIN_0_SET1; +    regs.mute_till_ld            = adf4360_regs_t::MUTE_TILL_LD_ENB; +    regs.output_power_level      = adf4360_regs_t::OUTPUT_POWER_LEVEL_3_5MA; +    regs.current_setting1        = adf4360_regs_t::CURRENT_SETTING1_0_31MA; +    regs.current_setting2        = adf4360_regs_t::CURRENT_SETTING2_0_31MA; +    regs.power_down              = adf4360_regs_t::POWER_DOWN_NORMAL_OP; +    regs.prescaler_value         = prescaler_to_enum[P]; +    regs.a_counter               = A; +    regs.b_counter               = B; +    regs.cp_gain_1               = adf4360_regs_t::CP_GAIN_1_SET1; +    regs.divide_by_2_output      = (_div2[unit])? +                                    adf4360_regs_t::DIVIDE_BY_2_OUTPUT_DIV2 : +                                    adf4360_regs_t::DIVIDE_BY_2_OUTPUT_FUND ; +    regs.divide_by_2_prescaler   = adf4360_regs_t::DIVIDE_BY_2_PRESCALER_FUND; +    regs.r_counter               = R; +    regs.ablpw                   = adf4360_regs_t::ABLPW_3_0NS; +    regs.lock_detect_precision   = adf4360_regs_t::LOCK_DETECT_PRECISION_5CYCLES; +    regs.test_mode_bit           = 0; +    regs.band_select_clock_div   = adf4360_regs_t::BAND_SELECT_CLOCK_DIV_8;      //write the registers -    std::vector<adf4360_regs_t::addr_t> addrs = list_of +    std::vector<adf4360_regs_t::addr_t> addrs = list_of //correct power-up sequence to write registers (R, C, N) +        (adf4360_regs_t::ADDR_RCOUNTER)          (adf4360_regs_t::ADDR_CONTROL)          (adf4360_regs_t::ADDR_NCOUNTER) -        (adf4360_regs_t::ADDR_RCOUNTER)      ;      BOOST_FOREACH(adf4360_regs_t::addr_t addr, addrs){          this->get_iface()->write_spi( @@ -243,7 +306,12 @@ double rfx_xcvr::set_lo_freq(      }      //return the actual frequency -    return target_freq; //TODO... and remember to check div2 +    double actual_freq = double(P*B + A) * ref_freq / double(R); +    if (_div2[unit]) actual_freq /= 2; +    if (rfx_debug) std::cerr << boost::format( +        "RFX tune: actual frequency %f Mhz" +    ) % (actual_freq/100e6) << std::endl; +    return actual_freq;  }  /***********************************************************************  | 
