Statistics
| Branch: | Tag: | Revision:

root / host / lib / usrp / usrp2 / clock_control.cpp @ 5b5696cb

History | View | Annotate | Download (4.08 KB)

1
//
2
// Copyright 2010 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

    
18
#include "usrp2_impl.hpp"
19
#include "clock_control.hpp"
20
#include "ad9510_regs.hpp"
21
#include "usrp2_regs.hpp" //spi slave constants
22
#include <boost/cstdint.hpp>
23

    
24
using namespace uhd::usrp;
25

    
26
/*!
27
 * A usrp2 clock control specific to the ad9510 ic.
28
 */
29
class clock_control_ad9510 : public clock_control{
30
public:
31
    clock_control_ad9510(usrp2_impl *impl){
32
        _impl = impl;
33

    
34
        _ad9510_regs.cp_current_setting = ad9510_regs_t::CP_CURRENT_SETTING_3_0MA;
35
        this->write_reg(0x09);
36

    
37
        //100mhz = 10mhz/R * (P*B + A)
38

    
39
        _ad9510_regs.pll_power_down = ad9510_regs_t::PLL_POWER_DOWN_NORMAL;
40
        _ad9510_regs.prescaler_value = ad9510_regs_t::PRESCALER_VALUE_DIV2;
41
        this->write_reg(0x0A);
42

    
43
        _ad9510_regs.acounter = 0;
44
        this->write_reg(0x04);
45

    
46
        _ad9510_regs.bcounter_msb = 0;
47
        _ad9510_regs.bcounter_lsb = 5;
48
        this->write_reg(0x05);
49
        this->write_reg(0x06);
50

    
51
        _ad9510_regs.ref_counter_msb = 0;
52
        _ad9510_regs.ref_counter_lsb = 1; // r divider = 1
53
        this->write_reg(0x0B);
54
        this->write_reg(0x0C);
55

    
56
        /* regs will be updated in commands below */
57

    
58
        this->enable_external_ref(false);
59
        this->enable_rx_dboard_clock(false);
60
        this->enable_tx_dboard_clock(false);
61
    }
62

    
63
    ~clock_control_ad9510(void){
64
        /* NOP */
65
    }
66

    
67
    void enable_rx_dboard_clock(bool enb){
68
        _ad9510_regs.power_down_lvds_cmos_out7 = enb? 0 : 1;
69
        _ad9510_regs.lvds_cmos_select_out7 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT7_CMOS;
70
        _ad9510_regs.output_level_lvds_out7 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT7_1_75MA;
71
        this->write_reg(0x43);
72
        this->update_regs();
73
    }
74

    
75
    void enable_tx_dboard_clock(bool enb){
76
        _ad9510_regs.power_down_lvds_cmos_out6 = enb? 0 : 1;
77
        _ad9510_regs.lvds_cmos_select_out6 = ad9510_regs_t::LVDS_CMOS_SELECT_OUT6_CMOS;
78
        _ad9510_regs.output_level_lvds_out6 = ad9510_regs_t::OUTPUT_LEVEL_LVDS_OUT6_1_75MA;
79
        this->write_reg(0x42);
80
        this->update_regs();
81
    }
82

    
83
    /*!
84
     * If we are to use an external reference, enable the charge pump.
85
     * \param enb true to enable the CP
86
     */
87
    void enable_external_ref(bool enb){
88
        _ad9510_regs.charge_pump_mode = (enb)?
89
            ad9510_regs_t::CHARGE_PUMP_MODE_NORMAL :
90
            ad9510_regs_t::CHARGE_PUMP_MODE_3STATE ;
91
        _ad9510_regs.pll_mux_control = ad9510_regs_t::PLL_MUX_CONTROL_DLD_HIGH;
92
        _ad9510_regs.pfd_polarity = ad9510_regs_t::PFD_POLARITY_POS;
93
        this->write_reg(0x08);
94
        this->update_regs();
95
    }
96

    
97
private:
98
    /*!
99
     * Write a single register to the spi regs.
100
     * \param addr the address to write
101
     */
102
    void write_reg(boost::uint8_t addr){
103
        boost::uint32_t data = _ad9510_regs.get_write_reg(addr);
104
        _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/);
105
    }
106

    
107
    /*!
108
     * Tells the ad9510 to latch the settings into the operational registers.
109
     */
110
    void update_regs(void){
111
        _ad9510_regs.update_registers = 1;
112
        this->write_reg(0x5a);
113
    }
114

    
115
    usrp2_impl *_impl;
116
    ad9510_regs_t _ad9510_regs;
117
};
118

    
119
/***********************************************************************
120
 * Public make function for the ad9510 clock control
121
 **********************************************************************/
122
clock_control::sptr clock_control::make_ad9510(usrp2_impl *impl){
123
    return clock_control::sptr(new clock_control_ad9510(impl));
124
}