Revision 9cb9e7d5

b/host/lib/usrp/CMakeLists.txt
32 32
)
33 33

  
34 34
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt)
35
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/CMakeLists.txt)
35 36
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt)
b/host/lib/usrp/usrp1/CMakeLists.txt
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
#This file will be included by cmake, use absolute paths!
19

  
20
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/include)
21

  
22
LIBUHD_APPEND_SOURCES(
23
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.cpp
24
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.hpp
25
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.cpp
26
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.hpp
27
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_impl.cpp
28
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_impl.cpp
29
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_iface.cpp
30
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dsp_impl.cpp
31
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/io_impl.cpp
32
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/mboard_impl.cpp
33
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.cpp
34
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.hpp
35
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.cpp
36
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.hpp
37
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.cpp
38
    ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.hpp
39
)
b/host/lib/usrp/usrp1/clock_ctrl.cpp
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 "clock_ctrl.hpp"
19
#include "fpga_regs_standard.h"
20
#include <uhd/utils/assert.hpp>
21
#include <boost/cstdint.hpp>
22
#include <boost/assign/list_of.hpp>
23
#include <boost/foreach.hpp>
24
#include <utility>
25
#include <iostream>
26

  
27
using namespace uhd;
28

  
29
/***********************************************************************
30
 * Constants
31
 **********************************************************************/
32
static const double master_clock_rate = 64e6;
33

  
34
/***********************************************************************
35
 * Clock Control Implementation
36
 **********************************************************************/
37
class usrp1_clock_ctrl_impl : public usrp1_clock_ctrl {
38
public:
39
    usrp1_clock_ctrl_impl(usrp1_iface::sptr iface)
40
    {
41
        _iface = iface;
42
    }
43

  
44
    double get_master_clock_freq(void)
45
    {
46
        return master_clock_rate; 
47
    }
48

  
49
    /***********************************************************************
50
     * RX Dboard Clock Control (output 9, divider 3)
51
     **********************************************************************/
52
    void enable_rx_dboard_clock(bool)
53
    {
54
        std::cerr << "USRP: enable_rx_dboard_clock() disabled" << std::endl;
55
        _iface->poke32(FR_RX_A_REFCLK, 0);
56
        _iface->poke32(FR_RX_B_REFCLK, 0);
57
    }
58

  
59
    std::vector<double> get_rx_dboard_clock_rates(void)
60
    {
61
#if 0 
62
        std::vector<double> rates;
63
        for (size_t div = 1; div <= 127; div++)
64
            rates.push_back(master_clock_rate / div);
65
        return rates;
66
#else
67
        return std::vector<double>(1, 64e6);
68
#endif
69
    }
70

  
71
    /*
72
     * Daughterboard reference clock register
73
     *
74
     * Bit  7    - 1 turns on refclk, 0 allows IO use
75
     * Bits 6:0  - Divider value
76
     */
77
    void set_rx_dboard_clock_rate(double)
78
    {
79
#if 0
80
        assert_has(get_rx_dboard_clock_rates(), rate, "rx dboard clock rate");
81
        size_t divider = size_t(rate/master_clock_rate);
82
        _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80);
83
#else
84
        std::cerr << "USRP: set_rx_dboard_clock_rate() disabled" << std::endl;
85
        _iface->poke32(FR_RX_A_REFCLK, 0);
86
        _iface->poke32(FR_RX_B_REFCLK, 0);
87
#endif
88
    }
89

  
90
    /***********************************************************************
91
     * TX Dboard Clock Control
92
     **********************************************************************/
93
    void enable_tx_dboard_clock(bool)
94
    {
95
        std::cerr << "USRP: set_tx_dboard_clock() disabled" << std::endl;
96
        _iface->poke32(FR_TX_A_REFCLK, 0);
97
        _iface->poke32(FR_TX_B_REFCLK, 0);
98

  
99
    }
100

  
101
    std::vector<double> get_tx_dboard_clock_rates(void)
102
    {
103
        return get_rx_dboard_clock_rates(); //same master clock, same dividers...
104
    }
105

  
106
    void set_tx_dboard_clock_rate(double)
107
    {
108
        std::cerr << "USRP: set_tx_dboard_clock_rate() disabled" << std::endl;
109
        _iface->poke32(FR_TX_A_REFCLK, 0);
110
        _iface->poke32(FR_TX_B_REFCLK, 0);
111
    }
112

  
113
private:
114
    usrp1_iface::sptr _iface;
115

  
116
};
117

  
118
/***********************************************************************
119
 * Clock Control Make
120
 **********************************************************************/
121
usrp1_clock_ctrl::sptr usrp1_clock_ctrl::make(usrp1_iface::sptr iface)
122
{
123
    return sptr(new usrp1_clock_ctrl_impl(iface));
124
}
b/host/lib/usrp/usrp1/clock_ctrl.hpp
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
#ifndef INCLUDED_USRP1_CLOCK_CTRL_HPP
19
#define INCLUDED_USRP1_CLOCK_CTRL_HPP
20

  
21
#include "usrp1_iface.hpp"
22
#include <boost/shared_ptr.hpp>
23
#include <boost/utility.hpp>
24
#include <vector>
25

  
26
/*!
27
 * The usrp1 clock control:
28
 * - Setup system clocks.
29
 * - Disable/enable clock lines.
30
 */
31
class usrp1_clock_ctrl : boost::noncopyable{
32
public:
33
    typedef boost::shared_ptr<usrp1_clock_ctrl> sptr;
34

  
35
    /*!
36
     * Make a new clock control object.
37
     * \param iface the usrp1 iface object
38
     * \return the clock control object
39
     */
40
    static sptr make(usrp1_iface::sptr iface);
41

  
42
    /*!
43
     * Get the rate of the fpga clock line.
44
     * \return the fpga clock rate in Hz
45
     */
46
    virtual double get_master_clock_freq(void) = 0;
47

  
48
    /*!
49
     * Get the possible rates of the rx dboard clock.
50
     * \return a vector of clock rates in Hz
51
     */
52
    virtual std::vector<double> get_rx_dboard_clock_rates(void) = 0;
53

  
54
    /*!
55
     * Get the possible rates of the tx dboard clock.
56
     * \return a vector of clock rates in Hz
57
     */
58
    virtual std::vector<double> get_tx_dboard_clock_rates(void) = 0;
59

  
60
    /*!
61
     * Set the rx dboard clock rate to a possible rate.
62
     * \param rate the new clock rate in Hz
63
     * \throw exception when rate cannot be achieved
64
     */
65
    virtual void set_rx_dboard_clock_rate(double rate) = 0;
66

  
67
    /*!
68
     * Set the tx dboard clock rate to a possible rate.
69
     * \param rate the new clock rate in Hz
70
     * \throw exception when rate cannot be achieved
71
     */
72
    virtual void set_tx_dboard_clock_rate(double rate) = 0;
73

  
74
    /*!
75
     * Enable/disable the rx dboard clock.
76
     * \param enb true to enable
77
     */
78
    virtual void enable_rx_dboard_clock(bool enb) = 0;
79

  
80
    /*!
81
     * Enable/disable the tx dboard clock.
82
     * \param enb true to enable
83
     */
84
    virtual void enable_tx_dboard_clock(bool enb) = 0;
85

  
86
};
87

  
88
#endif /* INCLUDED_USRP1_CLOCK_CTRL_HPP */
b/host/lib/usrp/usrp1/codec_ctrl.cpp
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 "codec_ctrl.hpp"
19
#include "usrp_commands.h"
20
#include "fpga_regs_standard.h"
21
#include "usrp_spi_defs.h"
22
#include "ad9862_regs.hpp"
23
#include <uhd/types/dict.hpp>
24
#include <uhd/utils/assert.hpp>
25
#include <uhd/utils/algorithm.hpp>
26
#include <uhd/utils/byteswap.hpp>
27
#include <boost/cstdint.hpp>
28
#include <boost/tuple/tuple.hpp>
29
#include <boost/math/special_functions/round.hpp>
30
#include <boost/assign/list_of.hpp>
31
#include <iostream>
32
#include <iomanip>
33
#include <cstdio>
34

  
35
using namespace uhd;
36

  
37
static const bool codec_debug = true; 
38

  
39
const gain_range_t usrp1_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1));
40
const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1);
41

  
42
/***********************************************************************
43
 * Codec Control Implementation
44
 **********************************************************************/
45
class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl {
46
public:
47
    //structors
48
    usrp1_codec_ctrl_impl(usrp1_iface::sptr iface);
49
    ~usrp1_codec_ctrl_impl(void);
50

  
51
    //aux adc and dac control
52
    float read_aux_adc(aux_adc_t which);
53
    void write_aux_dac(aux_dac_t which, float volts);
54

  
55
    //duc control
56
    bool set_duc_freq(double freq);
57

  
58
    //pga gain control
59
    void set_tx_pga_gain(float);
60
    float get_tx_pga_gain(void);
61
    void set_rx_pga_gain(float, char);
62
    float get_rx_pga_gain(char);
63

  
64
private:
65
    usrp1_iface::sptr _iface;
66
    ad9862_regs_t _ad9862_regs;
67
    aux_adc_t _last_aux_adc_a, _last_aux_adc_b;
68
    void send_reg(boost::uint8_t addr);
69
    void recv_reg(boost::uint8_t addr);
70

  
71
    //FIXME: poison
72
    double _tx_freq[4];
73
    unsigned int compute_freq_control_word_9862 (double master_freq,
74
                                                 double target_freq,
75
                                                 double *actual_freq);
76
};
77

  
78
/***********************************************************************
79
 * Codec Control Structors
80
 **********************************************************************/
81
usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface)
82
{
83
    _iface = iface;
84

  
85
    //soft reset
86
    _ad9862_regs.soft_reset = 1;
87
    this->send_reg(0);
88

  
89
    //initialize the codec register settings
90
    _ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO;
91
    _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB;
92
    _ad9862_regs.soft_reset = 0;
93

  
94
    //setup rx side of codec
95
    _ad9862_regs.byp_buffer_a = 1;
96
    _ad9862_regs.byp_buffer_b = 1;
97
    _ad9862_regs.buffer_a_pd = 1;
98
    _ad9862_regs.buffer_b_pd = 1;
99
    _ad9862_regs.rx_pga_a = 0;//0x1f;  //TODO bring under api control
100
    _ad9862_regs.rx_pga_b = 0;//0x1f;  //TODO bring under api control
101
    _ad9862_regs.rx_twos_comp = 1;
102
    _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS;
103

  
104
    //setup tx side of codec
105
    _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH;
106
    _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED;
107
    _ad9862_regs.tx_pga_gain = 199; //TODO bring under api control
108
    _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS;
109
    _ad9862_regs.interp = ad9862_regs_t::INTERP_4;
110
    _ad9862_regs.tx_twos_comp = 1;
111
    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO;
112
    _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS;
113
    _ad9862_regs.dac_a_coarse_gain = 0x3;
114
    _ad9862_regs.dac_b_coarse_gain = 0x3;
115

  
116
    //setup the dll
117
    _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL;
118
    _ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2;
119
    _ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST;
120

  
121
    //setup clockout
122
    _ad9862_regs.clkout2_div_factor = ad9862_regs_t::CLKOUT2_DIV_FACTOR_2;
123

  
124
    //write the register settings to the codec
125
    for (uint8_t addr = 0; addr <= 25; addr++) {
126
        this->send_reg(addr);
127
    }
128

  
129
    //aux adc clock
130
    _ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4;
131
    this->send_reg(34);
132
}
133

  
134
usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void)
135
{
136
    //set aux dacs to zero
137
    this->write_aux_dac(AUX_DAC_A, 0);
138
    this->write_aux_dac(AUX_DAC_B, 0);
139
    this->write_aux_dac(AUX_DAC_C, 0);
140
    this->write_aux_dac(AUX_DAC_D, 0);
141

  
142
    //power down
143
    _ad9862_regs.all_rx_pd = 1;
144
    this->send_reg(1);
145
    _ad9862_regs.tx_digital_pd = 1;
146
    _ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH;
147
    this->send_reg(8);
148
}
149

  
150
/***********************************************************************
151
 * Codec Control Gain Control Methods
152
 **********************************************************************/
153
void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain)
154
{
155
    int gain_word = int(63*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min));
156
    _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, 63);
157
    this->send_reg(16);
158
}
159

  
160
float usrp1_codec_ctrl_impl::get_tx_pga_gain(void)
161
{
162
    return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/63) + tx_pga_gain_range.min;
163
}
164

  
165
void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which)
166
{
167
    int gain_word = int(0x14*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min));
168
    gain_word = std::clip(gain_word, 0, 0x14);
169
    switch(which){
170
    case 'A':
171
        _ad9862_regs.rx_pga_a = gain_word;
172
        this->send_reg(2);
173
        return;
174
    case 'B':
175
        _ad9862_regs.rx_pga_b = gain_word;
176
        this->send_reg(3);
177
        return;
178
    default: UHD_THROW_INVALID_CODE_PATH();
179
    }
180
}
181

  
182
float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which)
183
{
184
    int gain_word;
185
    switch(which){
186
    case 'A': gain_word = _ad9862_regs.rx_pga_a; break;
187
    case 'B': gain_word = _ad9862_regs.rx_pga_b; break;
188
    default: UHD_THROW_INVALID_CODE_PATH();
189
    }
190
    return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/0x14) + rx_pga_gain_range.min;
191
}
192

  
193
/***********************************************************************
194
 * Codec Control AUX ADC Methods
195
 **********************************************************************/
196
static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low)
197
{
198
    return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff;
199
}
200

  
201
float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
202
{
203
    //check to see if the switch needs to be set
204
    bool write_switch = false;
205
    switch(which) {
206

  
207
    case AUX_ADC_A1:
208
    case AUX_ADC_A2:
209
        if (which != _last_aux_adc_a) {
210
            _ad9862_regs.select_a = (which == AUX_ADC_A1)?
211
                ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2;
212
            _last_aux_adc_a = which;
213
            write_switch = true;
214
        }
215
        break;
216

  
217
    case AUX_ADC_B1:
218
    case AUX_ADC_B2:
219
        if (which != _last_aux_adc_b) {
220
            _ad9862_regs.select_b = (which == AUX_ADC_B1)?
221
                ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2;
222
            _last_aux_adc_b = which;
223
            write_switch = true;
224
        }
225
        break;
226

  
227
    }
228

  
229
    //write the switch if it changed
230
    if(write_switch) this->send_reg(34);
231

  
232
    //map aux adcs to register values to read
233
    static const uhd::dict<aux_adc_t, boost::uint8_t> aux_dac_to_addr = boost::assign::map_list_of
234
        (AUX_ADC_A2, 26) (AUX_ADC_A1, 28)
235
        (AUX_ADC_B2, 30) (AUX_ADC_B1, 32)
236
    ;
237

  
238
    //read the value
239
    this->recv_reg(aux_dac_to_addr[which]+0);
240
    this->recv_reg(aux_dac_to_addr[which]+1);
241

  
242
    //return the value scaled to volts
243
    switch(which) {
244
    case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0);
245
    case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0);
246
    case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0);
247
    case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0);
248
    }
249
    UHD_ASSERT_THROW(false);
250
}
251

  
252
/***********************************************************************
253
 * Codec Control AUX DAC Methods
254
 **********************************************************************/
255
void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts)
256
{
257
    //special case for aux dac d (aka sigma delta word)
258
    if (which == AUX_DAC_D) {
259
        boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff);
260
        _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4);
261
        _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf);
262
        this->send_reg(42);
263
        this->send_reg(43);
264
        return;
265
    }
266

  
267
    //calculate the dac word for aux dac a, b, c
268
    boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff);
269

  
270
    //setup a lookup table for the aux dac params (reg ref, reg addr)
271
    typedef boost::tuple<boost::uint8_t*, boost::uint8_t> dac_params_t;
272
    uhd::dict<aux_dac_t, dac_params_t> aux_dac_to_params = boost::assign::map_list_of
273
        (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36))
274
        (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37))
275
        (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38))
276
    ;
277

  
278
    //set the aux dac register
279
    UHD_ASSERT_THROW(aux_dac_to_params.has_key(which));
280
    boost::uint8_t *reg_ref, reg_addr;
281
    boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which];
282
    *reg_ref = dac_word;
283
    this->send_reg(reg_addr);
284
}
285

  
286
/***********************************************************************
287
 * Codec Control SPI Methods
288
 **********************************************************************/
289
void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr)
290
{
291
    boost::uint32_t reg = _ad9862_regs.get_write_reg(addr);
292

  
293
    if (codec_debug) {
294
        std::cout.fill('0');
295
        std::cout << "codec control write reg: 0x";
296
        std::cout << std::setw(8) << std::hex << reg << std::endl;
297
    }
298
    _iface->transact_spi(SPI_ENABLE_CODEC_A,
299
                         spi_config_t::EDGE_RISE, reg, 16, false);
300
}
301

  
302
void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr)
303
{
304
    boost::uint32_t reg = _ad9862_regs.get_read_reg(addr);
305

  
306
    if (codec_debug) {
307
        std::cout.fill('0');
308
        std::cout << "codec control read reg: 0x";
309
        std::cout << std::setw(8) << std::hex << reg << std::endl;
310
    }
311

  
312
    boost::uint32_t ret = _iface->transact_spi(SPI_ENABLE_CODEC_A,
313
                                        spi_config_t::EDGE_RISE, reg, 16, true);
314

  
315
    if (codec_debug) {
316
        std::cout.fill('0');
317
        std::cout << "codec control read ret: 0x";
318
        std::cout << std::setw(8) << std::hex << ret << std::endl;
319
    }
320

  
321
    _ad9862_regs.set_reg(addr, boost::uint16_t(ret));
322
}
323

  
324
/***********************************************************************
325
 * DUC tuning 
326
 **********************************************************************/
327
unsigned int usrp1_codec_ctrl_impl::compute_freq_control_word_9862(
328
                    double master_freq, double target_freq, double *actual_freq)
329
{
330
    double sign = 1.0;
331
 
332
    if (target_freq < 0)
333
        sign = -1.0;
334
 
335
    int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0));
336
    *actual_freq = v * master_freq / pow (2.0, 24.0) * sign;
337
 
338
    fprintf(stdout,
339
       "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n",
340
       target_freq, *actual_freq, *actual_freq - target_freq, v);
341
 
342
    return (unsigned int) v;
343
}
344

  
345
bool usrp1_codec_ctrl_impl::set_duc_freq(double freq)
346
{
347
    int channel = 0;
348
    float dac_rate = 128e6;
349
 
350
    double coarse;
351

  
352
    std::cout << "duc_freq: " << freq << std::endl;
353

  
354
    // First coarse frequency
355
    double coarse_freq_1 = dac_rate / 8;
356
    // Second coarse frequency
357
    double coarse_freq_2 = dac_rate / 4;
358
    // Midpoint of [0 , freq1] range
359
    double coarse_limit_1 = coarse_freq_1 / 2;
360
    // Midpoint of [freq1 , freq2] range
361
    double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2;
362
    // Highest meaningful frequency
363
    double high_limit = (double) 44e6 / 128e6 * dac_rate;
364
 
365
    if (freq < -high_limit) {              // too low
366
        return false;
367
    }
368
    else if (freq < -coarse_limit_2) {     // For 64MHz: [-44, -24)
369
        _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;
370
        _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4;
371
        coarse = -coarse_freq_2;
372
    }
373
    else if (freq < -coarse_limit_1) {     // For 64MHz: [-24, -8)
374
        _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;
375
        _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8;
376
        coarse = -coarse_freq_1;
377
    }
378
    else if (freq < coarse_limit_1) {      // For 64MHz: [-8, 8)
379
        _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS;
380
        coarse = 0; 
381
    }
382
    else if (freq < coarse_limit_2) {      // For 64MHz: [8, 24)
383
        _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;
384
        _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8;
385
        coarse = coarse_freq_1;
386
    }
387
    else if (freq <= high_limit) {         // For 64MHz: [24, 44]
388
        _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;
389
        _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4;
390
        coarse = coarse_freq_2;
391
    }
392
    else {                                 // too high
393
        return false;
394
    }
395
 
396
    double fine = freq - coarse;
397
 
398
    // Compute fine tuning word...
399
    // This assumes we're running the 4x on-chip interpolator.
400
    // (This is required to use the fine modulator.)
401
 
402
    unsigned int v = compute_freq_control_word_9862 (dac_rate / 4, fine,
403
                                                     &_tx_freq[channel]);
404

  
405
    _tx_freq[channel] += coarse;         // adjust actual
406
    
407
    boost::uint8_t high;
408
    boost::uint8_t mid;
409
    boost::uint8_t low;
410
 
411
    high = (v >> 16) & 0xff;
412
    mid  = (v >>  8) & 0xff;
413
    low  = (v >>  0) & 0xff;
414
 
415
    // write the fine tuning word
416
    _ad9862_regs.ftw_23_16 = high;
417
    _ad9862_regs.ftw_15_8 = mid;
418
    _ad9862_regs.ftw_7_0 = low;
419
 
420
    _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO;
421
 
422
    if (fine < 0)
423
        _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT;
424
    else
425
        _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT;
426
 
427
    this->send_reg(20);
428
    this->send_reg(21);
429
    this->send_reg(22);
430
    this->send_reg(23);
431
 
432
    return true; 
433
}
434

  
435
/***********************************************************************
436
 * Codec Control Make
437
 **********************************************************************/
438
usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface)
439
{
440
    return sptr(new usrp1_codec_ctrl_impl(iface));
441
}
b/host/lib/usrp/usrp1/codec_ctrl.hpp
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
#ifndef INCLUDED_USRP1_CODEC_CTRL_HPP
19
#define INCLUDED_USRP1_CODEC_CTRL_HPP
20

  
21
#include "usrp1_iface.hpp"
22
#include <boost/shared_ptr.hpp>
23
#include <boost/utility.hpp>
24

  
25
/*!
26
 * The usrp1 codec control:
27
 * - Init/power down codec.
28
 * - Read aux adc, write aux dac.
29
 */
30
class usrp1_codec_ctrl : boost::noncopyable{
31
public:
32
    typedef boost::shared_ptr<usrp1_codec_ctrl> sptr;
33

  
34
    /*!
35
     * Make a new clock control object.
36
     * \param iface the usrp1 iface object
37
     * \return the clock control object
38
     */
39
    static sptr make(usrp1_iface::sptr iface);
40

  
41
    //! aux adc identifier constants
42
    enum aux_adc_t{
43
        AUX_ADC_A2 = 0xA2,
44
        AUX_ADC_A1 = 0xA1,
45
        AUX_ADC_B2 = 0xB2,
46
        AUX_ADC_B1 = 0xB1
47
    };
48

  
49
    /*!
50
     * Read an auxiliary adc:
51
     * The internals remember which aux adc was read last.
52
     * Therefore, the aux adc switch is only changed as needed.
53
     * \param which which of the 4 adcs
54
     * \return a value in volts
55
     */
56
    virtual float read_aux_adc(aux_adc_t which) = 0;
57

  
58
    //! aux dac identifier constants
59
    enum aux_dac_t{
60
        AUX_DAC_A = 0xA,
61
        AUX_DAC_B = 0xB,
62
        AUX_DAC_C = 0xC,
63
        AUX_DAC_D = 0xD
64
    };
65

  
66
    /*!
67
     * Write an auxiliary dac.
68
     * \param which which of the 4 dacs
69
     * \param volts the level in in volts
70
     */
71
    virtual void write_aux_dac(aux_dac_t which, float volts) = 0;
72

  
73
    virtual bool set_duc_freq(double freq) = 0;
74
};
75

  
76
#endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */
b/host/lib/usrp/usrp1/codec_impl.cpp
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 "usrp1_impl.hpp"
19
#include <uhd/usrp/codec_props.hpp>
20
#include <boost/bind.hpp>
21

  
22
using namespace uhd;
23
using namespace uhd::usrp;
24

  
25
/***********************************************************************
26
 * Helper Methods
27
 **********************************************************************/
28
void usrp1_impl::codec_init(void)
29
{
30
    //make proxies
31
    _rx_codec_proxy = wax_obj_proxy::make(
32
                          boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2),
33
                          boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2));
34

  
35
    _tx_codec_proxy = wax_obj_proxy::make(
36
                          boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2),
37
                          boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2));
38
}    
39

  
40
/***********************************************************************
41
 * RX Codec Properties
42
 **********************************************************************/
43
static const std::string ad9862_pga_gain_name = "ad9862 pga";
44

  
45
void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val)
46
{
47
    wax::obj key; std::string name;
48
    boost::tie(key, name) = extract_named_prop(key_);
49

  
50
    //handle the get request conditioned on the key
51
    switch(key.as<codec_prop_t>()) {
52
    case CODEC_PROP_NAME:
53
        val = std::string("usrp1 adc - ad9862");
54
        return;
55

  
56
    case CODEC_PROP_OTHERS:
57
        val = prop_names_t();
58
        return;
59

  
60
    case CODEC_PROP_GAIN_NAMES:
61
        val = prop_names_t(1, ad9862_pga_gain_name);
62
        return;
63

  
64
    case CODEC_PROP_GAIN_RANGE:
65
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
66
        val = usrp1_codec_ctrl::rx_pga_gain_range;
67
        return;
68

  
69
    case CODEC_PROP_GAIN_I:
70
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
71
        val = _codec_ctrl->get_rx_pga_gain('A');
72
        return;
73

  
74
    case CODEC_PROP_GAIN_Q:
75
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
76
        val = _codec_ctrl->get_rx_pga_gain('B');
77
        return;
78

  
79
    default: UHD_THROW_PROP_GET_ERROR();
80
    }
81
}
82

  
83
void usrp1_impl::rx_codec_set(const wax::obj &, const wax::obj &)
84
{
85
    wax::obj key; std::string name;
86
    boost::tie(key, name) = extract_named_prop(key_);
87

  
88
    //handle the set request conditioned on the key
89
    switch(key.as<codec_prop_t>()) {
90
    case CODEC_PROP_GAIN_I:
91
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
92
        _codec_ctrl->set_rx_pga_gain(val.as<float>(), 'A');
93
        return;
94

  
95
    case CODEC_PROP_GAIN_Q:
96
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
97
        _codec_ctrl->set_rx_pga_gain(val.as<float>(), 'B');
98
        return;
99

  
100
    default: UHD_THROW_PROP_SET_ERROR();
101
    }
102
}
103

  
104
/***********************************************************************
105
 * TX Codec Properties
106
 **********************************************************************/
107
void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val)
108
{
109
    wax::obj key; std::string name;
110
    boost::tie(key, name) = extract_named_prop(key_);
111

  
112
    //handle the get request conditioned on the key
113
    switch(key.as<codec_prop_t>()) {
114
    case CODEC_PROP_NAME:
115
        val = std::string("usrp1 dac - ad9862");
116
        return;
117

  
118
    case CODEC_PROP_OTHERS:
119
        val = prop_names_t();
120
        return;
121

  
122
    case CODEC_PROP_GAIN_NAMES:
123
        val = prop_names_t(1, ad9862_pga_gain_name);
124
        return;
125

  
126
    case CODEC_PROP_GAIN_RANGE:
127
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
128
        val = usrp1_codec_ctrl::tx_pga_gain_range;
129
        return;
130

  
131
    case CODEC_PROP_GAIN_I: //only one gain for I and Q
132
    case CODEC_PROP_GAIN_Q:
133
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
134
        val = _codec_ctrl->get_tx_pga_gain();
135
        return;
136

  
137
    default: UHD_THROW_PROP_GET_ERROR();
138
    }
139
}
140

  
141
void usrp1_impl::tx_codec_set(const wax::obj &, const wax::obj &)
142
{
143
    wax::obj key; std::string name;
144
    boost::tie(key, name) = extract_named_prop(key_);
145

  
146
    //handle the set request conditioned on the key
147
    switch(key.as<codec_prop_t>()){
148
    case CODEC_PROP_GAIN_I: //only one gain for I and Q
149
    case CODEC_PROP_GAIN_Q:
150
        UHD_ASSERT_THROW(name == ad9862_pga_gain_name);
151
        _codec_ctrl->set_tx_pga_gain(val.as<float>());
152
        return;
153

  
154
    default: UHD_THROW_PROP_SET_ERROR();
155
    }
156
}
b/host/lib/usrp/usrp1/dboard_iface.cpp
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 "usrp1_iface.hpp"
19
#include "fpga_regs_common.h"
20
#include "usrp_spi_defs.h"
21
#include "clock_ctrl.hpp"
22
#include "codec_ctrl.hpp"
23
#include <uhd/usrp/dboard_iface.hpp>
24
#include <uhd/types/dict.hpp>
25
#include <uhd/utils/assert.hpp>
26
#include <boost/assign/list_of.hpp>
27
#include <iostream>
28

  
29
using namespace uhd;
30
using namespace uhd::usrp;
31
using namespace boost::assign;
32

  
33
class usrp1_dboard_iface : public dboard_iface {
34
public:
35

  
36
    usrp1_dboard_iface(usrp1_iface::sptr iface,
37
                       usrp1_clock_ctrl::sptr clock,
38
                       usrp1_codec_ctrl::sptr codec)
39
    {
40
        _iface = iface;
41
        _clock = clock;
42
        _codec = codec;
43

  
44
        //init the clock rate shadows
45
        this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq());
46
        this->set_clock_rate(UNIT_TX, _clock->get_master_clock_freq());
47
    }
48

  
49
    ~usrp1_dboard_iface()
50
    {
51
        /* NOP */
52
    }
53

  
54
    std::string get_mboard_name()
55
    {
56
        return "usrp1";
57
    }
58

  
59
    void write_aux_dac(unit_t, aux_dac_t, float);
60
    float read_aux_adc(unit_t, aux_adc_t);
61

  
62
    void set_pin_ctrl(unit_t, boost::uint16_t);
63
    void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
64
    void set_gpio_ddr(unit_t, boost::uint16_t);
65
    void write_gpio(unit_t, boost::uint16_t);
66
    boost::uint16_t read_gpio(unit_t);
67

  
68
    void write_i2c(boost::uint8_t, const byte_vector_t &);
69
    byte_vector_t read_i2c(boost::uint8_t, size_t);
70

  
71
    void write_spi(unit_t unit,
72
                   const spi_config_t &config,
73
                   boost::uint32_t data,
74
                   size_t num_bits);
75

  
76
    boost::uint32_t read_write_spi(unit_t unit,
77
                                   const spi_config_t &config,
78
                                   boost::uint32_t data,
79
                                   size_t num_bits);
80

  
81
    void set_clock_rate(unit_t, double);
82
    std::vector<double> get_clock_rates(unit_t);
83
    double get_clock_rate(unit_t);
84
    void set_clock_enabled(unit_t, bool);
85

  
86
private:
87
    usrp1_iface::sptr _iface;
88
    usrp1_clock_ctrl::sptr _clock;
89
    usrp1_codec_ctrl::sptr _codec;
90
    uhd::dict<unit_t, double> _clock_rates;
91
};
92

  
93
/***********************************************************************
94
 * Make Function
95
 **********************************************************************/
96
dboard_iface::sptr make_usrp1_dboard_iface(usrp1_iface::sptr iface,
97
                                           usrp1_clock_ctrl::sptr clock,
98
                                           usrp1_codec_ctrl::sptr codec)
99
{
100
    return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec));
101
}
102

  
103
/***********************************************************************
104
 * Clock Rates
105
 **********************************************************************/
106
void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate)
107
{
108
    _clock_rates[unit] = rate;
109
    switch(unit) {
110
    case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate);    
111
    case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate);    
112
    }
113
}
114

  
115
/*
116
 * TODO: if this is a dbsrx return the rate of 4MHZ and set FPGA magic
117
 */
118
std::vector<double> usrp1_dboard_iface::get_clock_rates(unit_t unit)
119
{
120
    switch(unit) {
121
    case UNIT_RX: return _clock->get_rx_dboard_clock_rates();
122
    case UNIT_TX: return _clock->get_tx_dboard_clock_rates();
123
    default: UHD_THROW_INVALID_CODE_PATH();
124
    }
125
}
126

  
127
double usrp1_dboard_iface::get_clock_rate(unit_t unit)
128
{
129
    return _clock_rates[unit];
130
}
131

  
132
void usrp1_dboard_iface::set_clock_enabled(unit_t unit, bool enb)
133
{
134
    switch(unit) {
135
    case UNIT_RX: return _clock->enable_rx_dboard_clock(enb);
136
    case UNIT_TX: return _clock->enable_tx_dboard_clock(enb);
137
    }
138
}
139

  
140
/***********************************************************************
141
 * GPIO
142
 **********************************************************************/
143
void usrp1_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value)
144
{
145
    switch(unit) {
146
    case UNIT_RX:
147
         _iface->poke32(FR_ATR_MASK_1, value);
148
         _iface->poke32(FR_ATR_MASK_3, 0x00000000);
149
         break; 
150
    case UNIT_TX:
151
         _iface->poke32(FR_ATR_MASK_0, value);
152
         _iface->poke32(FR_ATR_MASK_2, 0x00000000);
153
         break;
154
    }
155
}
156

  
157
void usrp1_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value)
158
{
159
    switch(unit) {
160
    case UNIT_RX:
161
        _iface->poke32(FR_OE_1, 0xffff0000 | value);
162
        _iface->poke32(FR_OE_3, 0xffff0000);
163
        break; 
164
    case UNIT_TX:
165
        _iface->poke32(FR_OE_0, 0xffff0000 | value);
166
        _iface->poke32(FR_OE_2, 0xffff0000);
167
        break;
168
    }
169
}
170

  
171
void usrp1_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value)
172
{
173
    switch(unit) {
174
    case UNIT_RX:
175
        _iface->poke32(FR_IO_1, 0xffff0000 | value);
176
        break;
177
    case UNIT_TX:
178
        _iface->poke32(FR_IO_0, 0xffff0000 | value);
179
        break;
180
    }
181
}
182

  
183
boost::uint16_t usrp1_dboard_iface::read_gpio(unit_t unit)
184
{
185
    boost::uint32_t out_value;
186
    boost::uint16_t ret_value;
187

  
188
    switch(unit) {
189
    case UNIT_RX:
190
        //magic
191
        out_value = _iface->peek32(1);
192
        ret_value = (out_value >> 16) & 0x0000ffff;
193
        return ret_value;
194
    case UNIT_TX:
195
        //magic
196
        out_value = _iface->peek32(1);
197
        ret_value = (out_value >>  0) & 0x0000ffff;
198
        return ret_value;
199
    }
200
    UHD_ASSERT_THROW(false);
201
}
202

  
203
void usrp1_dboard_iface::set_atr_reg(unit_t unit,
204
                                     atr_reg_t atr, boost::uint16_t value)
205
{
206
    if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX)) {
207
        std::cerr << "error: set_atr_reg(): unsupported state" << std::endl;
208
        return;
209
    }
210

  
211
    switch(unit) {
212
    case UNIT_RX:
213
        _iface->poke32(FR_ATR_RXVAL_1, value);
214
        _iface->poke32(FR_ATR_RXVAL_3, 0x0000);
215
        break; 
216
    case UNIT_TX:
217
        //_iface->poke32(FR_ATR_TXVAL_0, value);
218
        _iface->poke32(FR_ATR_TXVAL_0, 0x0000);
219
        _iface->poke32(FR_ATR_TXVAL_2, 0x0000);
220
        break;
221
    }
222
}
223
/***********************************************************************
224
 * SPI
225
 **********************************************************************/
226
/*!
227
 * Static function to convert a unit type to a spi slave device number.
228
 * \param unit the dboard interface unit type enum
229
 * \return the slave device number
230
 */
231
static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit)
232
{
233
    switch(unit) {
234
    case dboard_iface::UNIT_TX: return SPI_ENABLE_TX_A; 
235
    case dboard_iface::UNIT_RX: return SPI_ENABLE_RX_A;
236
    }
237
    throw std::invalid_argument("unknown unit type");
238

  
239
}
240

  
241
void usrp1_dboard_iface::write_spi(unit_t unit,
242
                                   const spi_config_t &config,
243
                                   boost::uint32_t data,
244
                                   size_t num_bits)
245
{
246
    _iface->transact_spi(unit_to_otw_spi_dev(unit),
247
                         config, data, num_bits, false);
248
}
249

  
250
boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit,
251
                                                   const spi_config_t &config,
252
                                                   boost::uint32_t data,
253
                                                   size_t num_bits)
254
{
255
    return _iface->transact_spi(unit_to_otw_spi_dev(unit),
256
                                config, data, num_bits, true);
257
}
258

  
259
/***********************************************************************
260
 * I2C
261
 **********************************************************************/
262
void usrp1_dboard_iface::write_i2c(boost::uint8_t addr,
263
                                   const byte_vector_t &bytes)
264
{
265
    return _iface->write_i2c(addr, bytes);
266
}
267

  
268
byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr,
269
                                           size_t num_bytes)
270
{
271
    return _iface->read_i2c(addr, num_bytes);
272
}
273

  
274
/***********************************************************************
275
 * Aux DAX/ADC
276
 **********************************************************************/
277
void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t,
278
                                       aux_dac_t which, float value)
279
{
280
    //same aux dacs for each unit
281
    static const uhd::dict<aux_dac_t, usrp1_codec_ctrl::aux_dac_t>
282
        which_to_aux_dac = map_list_of
283
                                     (AUX_DAC_A, usrp1_codec_ctrl::AUX_DAC_A)
284
                                     (AUX_DAC_B, usrp1_codec_ctrl::AUX_DAC_B)
285
                                     (AUX_DAC_C, usrp1_codec_ctrl::AUX_DAC_C)
286
                                     (AUX_DAC_D, usrp1_codec_ctrl::AUX_DAC_D);
287

  
288
    _codec->write_aux_dac(which_to_aux_dac[which], value);
289
}
290

  
291
float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
292
                                       aux_adc_t which)
293
{
294
    static const
295
    uhd::dict<unit_t, uhd::dict<aux_adc_t, usrp1_codec_ctrl::aux_adc_t> >
296
        unit_to_which_to_aux_adc = map_list_of(UNIT_RX, map_list_of
297
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A1)
298
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B1))
299
                                              (UNIT_TX, map_list_of
300
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A2)
301
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B2));
302

  
303
    return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]);
304
}
b/host/lib/usrp/usrp1/dboard_impl.cpp
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 "usrp1_impl.hpp"
19
#include "usrp_i2c_addr.h"
20
#include "../dsp_utils.hpp"
21
#include "../misc_utils.hpp"
22
#include <uhd/utils/assert.hpp>
23
#include <uhd/usrp/dboard_props.hpp>
24
#include <uhd/usrp/subdev_props.hpp>
25
#include <boost/bind.hpp>
26
#include <iostream>
27

  
28
using namespace uhd;
29
using namespace uhd::usrp;
30

  
31
/***********************************************************************
32
 * Dboard Initialization
33
 **********************************************************************/
34
void usrp1_impl::dboard_init(void)
35
{
36
    _rx_db_eeprom = dboard_eeprom_t(
37
          _iface->read_eeprom(I2C_ADDR_RX_A, 0, dboard_eeprom_t::num_bytes()));
38

  
39
    _tx_db_eeprom = dboard_eeprom_t(
40
          _iface->read_eeprom(I2C_ADDR_TX_A, 0, dboard_eeprom_t::num_bytes()));
41

  
42

  
43
    //create a new dboard interface and manager
44
    _dboard_iface = make_usrp1_dboard_iface(_iface, _clock_ctrl, _codec_ctrl);
45

  
46
    _dboard_manager = dboard_manager::make(_rx_db_eeprom.id,
47
                                           _tx_db_eeprom.id,
48
                                           _dboard_iface);
49

  
50
    //setup the dboard proxies
51
    _rx_dboard_proxy = wax_obj_proxy::make(
52
                         boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2),
53
                         boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2));
54

  
55
    _tx_dboard_proxy = wax_obj_proxy::make(
56
                         boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2),
57
                         boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2));
58

  
59
}
60
/***********************************************************************
61
 * Helper functions 
62
 **********************************************************************/
63
//static int slot_to_i2c_addr (int slot)
64
//{
65
//    switch (slot) {
66
//    case SLOT_TX_A:
67
//        return I2C_ADDR_TX_A;
68
//    case SLOT_RX_A:
69
//        return I2C_ADDR_RX_A;
70
//    case SLOT_TX_B:
71
//        return I2C_ADDR_TX_B;
72
//    case SLOT_RX_B:
73
//        return I2C_ADDR_RX_B;
74
//    default:
75
//        return -1;
76
//    }
77
//}
78

  
79

  
80
/***********************************************************************
81
 * RX Dboard Get
82
 **********************************************************************/
83
void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val)
84
{
85
    wax::obj key; std::string name;
86
    boost::tie(key, name) = extract_named_prop(key_);
87

  
88
    //handle the get request conditioned on the key
89
    switch(key.as<dboard_prop_t>()){
90
    case DBOARD_PROP_NAME:
91
        val = std::string("usrp1 dboard (rx unit)");
92
        return;
93

  
94
    case DBOARD_PROP_SUBDEV:
95
        val = _dboard_manager->get_rx_subdev(name);
96
        return;
97

  
98
    case DBOARD_PROP_SUBDEV_NAMES:
99
        val = _dboard_manager->get_rx_subdev_names();
100
        return;
101

  
102
    case DBOARD_PROP_DBOARD_ID:
103
        val = _rx_db_eeprom.id;
104
        return;
105

  
106
    case DBOARD_PROP_DBOARD_IFACE:
107
        val = _dboard_iface;
108
        return;
109

  
110
    case DBOARD_PROP_CODEC:
111
        val = _rx_codec_proxy->get_link();
112
        return;
113

  
114
    case DBOARD_PROP_GAIN_GROUP:
115
        val = make_gain_group(_dboard_manager->get_rx_subdev(name),
116
                              _rx_codec_proxy->get_link());
117
        return;
118

  
119
    default: UHD_THROW_PROP_GET_ERROR();
120
    }
121
}
122

  
123
/***********************************************************************
124
 * RX Dboard Set
125
 **********************************************************************/
126
void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val)
127
{
128
    switch(key.as<dboard_prop_t>()) {
129
    case DBOARD_PROP_DBOARD_ID:
130
        _rx_db_eeprom.id = val.as<dboard_id_t>();
131
        _iface->write_eeprom(I2C_ADDR_RX_A, 0, 
132
                             _rx_db_eeprom.get_eeprom_bytes());
133
        return;
134

  
135
    default:
136
        UHD_THROW_PROP_SET_ERROR();
137
    }
138
}
139

  
140
/***********************************************************************
141
 * TX Dboard Get
142
 **********************************************************************/
143
void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val)
144
{
145
    wax::obj key; std::string name;
146
    boost::tie(key, name) = extract_named_prop(key_);
147

  
148
    //handle the get request conditioned on the key
149
    switch(key.as<dboard_prop_t>()){
150
    case DBOARD_PROP_NAME:
151
        val = std::string("usrp1 dboard (tx unit)");
152
        return;
153

  
154
    case DBOARD_PROP_SUBDEV:
155
        val = _dboard_manager->get_tx_subdev(name);
156
        return;
157

  
158
    case DBOARD_PROP_SUBDEV_NAMES:
159
        val = _dboard_manager->get_tx_subdev_names();
160
        return;
161

  
162
    case DBOARD_PROP_DBOARD_ID:
163
        val = _tx_db_eeprom.id;
164
        return;
165

  
166
    case DBOARD_PROP_DBOARD_IFACE:
167
        val = _dboard_iface;
168
        return;
169

  
170
    case DBOARD_PROP_CODEC:
171
        val = _tx_codec_proxy->get_link();
172
        return;
173

  
174
    case DBOARD_PROP_GAIN_GROUP:
175
        val = make_gain_group(_dboard_manager->get_tx_subdev(name),
176
                              _tx_codec_proxy->get_link());
177
        return;
178

  
179
    default: UHD_THROW_PROP_GET_ERROR();
180
    }
181
}
182

  
183
/***********************************************************************
184
 * TX Dboard Set
185
 **********************************************************************/
186
void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val)
187
{
188
    switch(key.as<dboard_prop_t>()) {
189
    case DBOARD_PROP_DBOARD_ID:
190
        _tx_db_eeprom.id = val.as<dboard_id_t>();
191
        _iface->write_eeprom(I2C_ADDR_TX_A, 0, _tx_db_eeprom.get_eeprom_bytes());
192
        return;
193

  
194
    default: UHD_THROW_PROP_SET_ERROR();
195
    }
196
}
b/host/lib/usrp/usrp1/dsp_impl.cpp
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.
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff