Revision 51a9c2d4

b/host/lib/CMakeLists.txt
103 103
LIST(APPEND libuhd_sources
104 104
    usrp/usrp2/clock_control.cpp
105 105
    usrp/usrp2/dboard_impl.cpp
106
    usrp/usrp2/dboard_interface.cpp
106
    usrp/usrp2/dboard_iface.cpp
107 107
    usrp/usrp2/dsp_impl.cpp
108 108
    usrp/usrp2/io_impl.cpp
109 109
    usrp/usrp2/mboard_impl.cpp
110
    usrp/usrp2/usrp2_iface.cpp
110 111
    usrp/usrp2/usrp2_impl.cpp
111 112
)
112 113

  
b/host/lib/usrp/usrp2/clock_control.cpp
28 28
 */
29 29
class clock_control_ad9510 : public clock_control{
30 30
public:
31
    clock_control_ad9510(usrp2_impl *impl){
32
        _impl = impl;
31
    clock_control_ad9510(usrp2_iface::sptr iface){
32
        _iface = iface;
33 33

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

  
72 72
    ~clock_control_ad9510(void){
73 73
        /* private clock enables, must be set here */
74
        //this->enable_dac_clock(false);
75
        //this->enable_adc_clock(false); //FIXME cant do yet
74
        this->enable_dac_clock(false);
75
        this->enable_adc_clock(false);
76 76
    }
77 77

  
78 78
    //uses output clock 7 (cmos)
......
114 114
     */
115 115
    void write_reg(boost::uint8_t addr){
116 116
        boost::uint32_t data = _ad9510_regs.get_write_reg(addr);
117
        _impl->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/);
117
        _iface->transact_spi(SPI_SS_AD9510, spi_config_t::EDGE_RISE, data, 24, false /*no rb*/);
118 118
    }
119 119

  
120 120
    /*!
......
144 144
        this->update_regs();
145 145
    }
146 146

  
147
    usrp2_impl *_impl;
147
    usrp2_iface::sptr _iface;
148 148
    ad9510_regs_t _ad9510_regs;
149 149
};
150 150

  
151 151
/***********************************************************************
152 152
 * Public make function for the ad9510 clock control
153 153
 **********************************************************************/
154
clock_control::sptr clock_control::make_ad9510(usrp2_impl *impl){
155
    return clock_control::sptr(new clock_control_ad9510(impl));
154
clock_control::sptr clock_control::make_ad9510(usrp2_iface::sptr iface){
155
    return clock_control::sptr(new clock_control_ad9510(iface));
156 156
}
b/host/lib/usrp/usrp2/clock_control.hpp
18 18
#ifndef INCLUDED_CLOCK_CONTROL_HPP
19 19
#define INCLUDED_CLOCK_CONTROL_HPP
20 20

  
21
class usrp2_impl; //dummy class
22

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

  
......
29 28

  
30 29
    /*!
31 30
     * Make a clock config for the ad9510 ic.
32
     * \param impl a pointer to the usrp2 implementation object
31
     * \param _iface a pointer to the usrp2 interface object
33 32
     * \return a new clock control object
34 33
     */
35
    static sptr make_ad9510(usrp2_impl *impl);
34
    static sptr make_ad9510(usrp2_iface::sptr iface);
36 35

  
37 36
    /*!
38 37
     * Enable/disable the rx dboard clock.
b/host/lib/usrp/usrp2/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 "usrp2_iface.hpp"
19
#include "clock_control.hpp"
20
#include "usrp2_regs.hpp"
21
#include <uhd/types/dict.hpp>
22
#include <uhd/utils/assert.hpp>
23
#include <boost/assign/list_of.hpp>
24
#include <boost/asio.hpp> //htonl and ntohl
25
#include <algorithm>
26

  
27
using namespace uhd::usrp;
28

  
29
class usrp2_dboard_iface : public dboard_interface{
30
public:
31
    usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl);
32
    ~usrp2_dboard_iface(void);
33

  
34
    void write_aux_dac(unit_t, int, int);
35
    int read_aux_adc(unit_t, int);
36

  
37
    void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
38
    void set_gpio_ddr(unit_t, boost::uint16_t);
39
    boost::uint16_t read_gpio(unit_t);
40

  
41
    void write_i2c(int, const byte_vector_t &);
42
    byte_vector_t read_i2c(int, size_t);
43

  
44
    double get_clock_rate(unit_t);
45
    void set_clock_enabled(unit_t, bool);
46
    bool get_clock_enabled(unit_t);
47

  
48
    void write_spi(
49
        unit_t unit,
50
        const spi_config_t &config,
51
        boost::uint32_t data,
52
        size_t num_bits
53
    );
54

  
55
    boost::uint32_t read_write_spi(
56
        unit_t unit,
57
        const spi_config_t &config,
58
        boost::uint32_t data,
59
        size_t num_bits
60
    );
61

  
62
private:
63
    usrp2_iface::sptr _iface;
64
    clock_control::sptr _clk_ctrl;
65
    boost::uint32_t _ddr_shadow;
66
};
67

  
68
/***********************************************************************
69
 * Make Function
70
 **********************************************************************/
71
dboard_interface::sptr make_usrp2_dboard_iface(
72
    usrp2_iface::sptr iface,
73
    clock_control::sptr clk_ctrl
74
){
75
    return dboard_interface::sptr(new usrp2_dboard_iface(iface, clk_ctrl));
76
}
77

  
78
/***********************************************************************
79
 * Structors
80
 **********************************************************************/
81
usrp2_dboard_iface::usrp2_dboard_iface(usrp2_iface::sptr iface, clock_control::sptr clk_ctrl){
82
    _iface = iface;
83
    _clk_ctrl = clk_ctrl;
84
    _ddr_shadow = 0;
85

  
86
    //set the selection mux to use atr
87
    boost::uint32_t new_sels = 0x0;
88
    for(size_t i = 0; i < 16; i++){
89
        new_sels |= FRF_GPIO_SEL_ATR << (i*2);
90
    }
91
    _iface->poke32(FR_GPIO_TX_SEL, new_sels);
92
    _iface->poke32(FR_GPIO_RX_SEL, new_sels);
93
}
94

  
95
usrp2_dboard_iface::~usrp2_dboard_iface(void){
96
    /* NOP */
97
}
98

  
99
/***********************************************************************
100
 * Clocks
101
 **********************************************************************/
102
double usrp2_dboard_iface::get_clock_rate(unit_t){
103
    return _iface->get_master_clock_freq();
104
}
105

  
106
void usrp2_dboard_iface::set_clock_enabled(unit_t unit, bool enb){
107
    switch(unit){
108
    case UNIT_RX:
109
        _clk_ctrl->enable_rx_dboard_clock(enb);
110
        return;
111
    case UNIT_TX:
112
        _clk_ctrl->enable_tx_dboard_clock(enb);
113
        return;
114
    }
115
}
116

  
117
/***********************************************************************
118
 * GPIO
119
 **********************************************************************/
120
static int unit_to_shift(dboard_interface::unit_t unit){
121
    switch(unit){
122
    case dboard_interface::UNIT_RX: return 0;
123
    case dboard_interface::UNIT_TX: return 16;
124
    }
125
    throw std::runtime_error("unknown unit type");
126
}
127

  
128
void usrp2_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
129
    _ddr_shadow = \
130
        (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) |
131
        (boost::uint32_t(value) << unit_to_shift(unit));
132
    _iface->poke32(FR_GPIO_DDR, _ddr_shadow);
133
}
134

  
135
boost::uint16_t usrp2_dboard_iface::read_gpio(unit_t unit){
136
    return boost::uint16_t(_iface->peek32(FR_GPIO_IO) >> unit_to_shift(unit));
137
}
138

  
139
void usrp2_dboard_iface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){
140
    //define mapping of unit to atr regs to register address
141
    static const uhd::dict<
142
        unit_t, uhd::dict<atr_reg_t, boost::uint32_t>
143
    > unit_to_atr_to_addr = boost::assign::map_list_of
144
        (UNIT_RX, boost::assign::map_list_of
145
            (ATR_REG_IDLE,        FR_ATR_IDLE_RXSIDE)
146
            (ATR_REG_TX_ONLY,     FR_ATR_INTX_RXSIDE)
147
            (ATR_REG_RX_ONLY,     FR_ATR_INRX_RXSIDE)
148
            (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE)
149
        )
150
        (UNIT_TX, boost::assign::map_list_of
151
            (ATR_REG_IDLE,        FR_ATR_IDLE_TXSIDE)
152
            (ATR_REG_TX_ONLY,     FR_ATR_INTX_TXSIDE)
153
            (ATR_REG_RX_ONLY,     FR_ATR_INRX_TXSIDE)
154
            (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE)
155
        )
156
    ;
157
    _iface->poke16(unit_to_atr_to_addr[unit][atr], value);
158
}
159

  
160
/***********************************************************************
161
 * SPI
162
 **********************************************************************/
163
/*!
164
 * Static function to convert a unit type enum
165
 * to an over-the-wire value for the spi device.
166
 * \param unit the dboard interface unit type enum
167
 * \return an over the wire representation
168
 */
169
static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){
170
    switch(unit){
171
    case dboard_interface::UNIT_TX: return SPI_SS_TX_DB;
172
    case dboard_interface::UNIT_RX: return SPI_SS_RX_DB;
173
    }
174
    throw std::invalid_argument("unknown unit type");
175
}
176

  
177
void usrp2_dboard_iface::write_spi(
178
    unit_t unit,
179
    const spi_config_t &config,
180
    boost::uint32_t data,
181
    size_t num_bits
182
){
183
    _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/);
184
}
185

  
186
boost::uint32_t usrp2_dboard_iface::read_write_spi(
187
    unit_t unit,
188
    const spi_config_t &config,
189
    boost::uint32_t data,
190
    size_t num_bits
191
){
192
    return _iface->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/);
193
}
194

  
195
/***********************************************************************
196
 * I2C
197
 **********************************************************************/
198
void usrp2_dboard_iface::write_i2c(int i2c_addr, const byte_vector_t &buf){
199
    //setup the out data
200
    usrp2_ctrl_data_t out_data;
201
    out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO);
202
    out_data.data.i2c_args.addr = i2c_addr;
203
    out_data.data.i2c_args.bytes = buf.size();
204

  
205
    //limitation of i2c transaction size
206
    ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data));
207

  
208
    //copy in the data
209
    std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data);
210

  
211
    //send and recv
212
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
213
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE);
214
}
215

  
216
dboard_interface::byte_vector_t usrp2_dboard_iface::read_i2c(int i2c_addr, size_t num_bytes){
217
    //setup the out data
218
    usrp2_ctrl_data_t out_data;
219
    out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO);
220
    out_data.data.i2c_args.addr = i2c_addr;
221
    out_data.data.i2c_args.bytes = num_bytes;
222

  
223
    //limitation of i2c transaction size
224
    ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data));
225

  
226
    //send and recv
227
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
228
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE);
229
    ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes);
230

  
231
    //copy out the data
232
    byte_vector_t result(num_bytes);
233
    std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin());
234
    return result;
235
}
236

  
237
/***********************************************************************
238
 * Aux DAX/ADC
239
 **********************************************************************/
240
/*!
241
 * Static function to convert a unit type enum
242
 * to an over-the-wire value for the usrp2 control.
243
 * \param unit the dboard interface unit type enum
244
 * \return an over the wire representation
245
 */
246
static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){
247
    switch(unit){
248
    case dboard_interface::UNIT_TX: return USRP2_DIR_TX;
249
    case dboard_interface::UNIT_RX: return USRP2_DIR_RX;
250
    }
251
    throw std::invalid_argument("unknown unit type");
252
}
253

  
254
void usrp2_dboard_iface::write_aux_dac(unit_t unit, int which, int value){
255
    //setup the out data
256
    usrp2_ctrl_data_t out_data;
257
    out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO);
258
    out_data.data.aux_args.dir = unit_to_otw(unit);
259
    out_data.data.aux_args.which = which;
260
    out_data.data.aux_args.value = htonl(value);
261

  
262
    //send and recv
263
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
264
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE);
265
}
266

  
267
int usrp2_dboard_iface::read_aux_adc(unit_t unit, int which){
268
    //setup the out data
269
    usrp2_ctrl_data_t out_data;
270
    out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO);
271
    out_data.data.aux_args.dir = unit_to_otw(unit);
272
    out_data.data.aux_args.which = which;
273

  
274
    //send and recv
275
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
276
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE);
277
    return ntohl(in_data.data.aux_args.value);
278
}
b/host/lib/usrp/usrp2/dboard_impl.cpp
22 22
#include <uhd/usrp/dboard_props.hpp>
23 23
#include <uhd/utils/assert.hpp>
24 24
#include <boost/format.hpp>
25
#include <boost/bind.hpp>
26
#include <boost/asio.hpp> //htonl and ntohl
25 27
#include <iostream>
26 28

  
27 29
using namespace uhd;
......
34 36
    //grab the dboard ids over the control line
35 37
    usrp2_ctrl_data_t out_data;
36 38
    out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_DBOARD_IDS_BRO);
37
    usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
39
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
38 40
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THESE_ARE_MY_DBOARD_IDS_DUDE);
39 41

  
40 42
    //extract the dboard ids an convert them
......
43 45

  
44 46
    //create a new dboard interface and manager
45 47
    dboard_interface::sptr _dboard_interface(
46
        make_usrp2_dboard_interface(this)
48
        make_usrp2_dboard_iface(_iface, _clk_ctrl)
47 49
    );
48 50
    _dboard_manager = dboard_manager::make(
49 51
        rx_dboard_id, tx_dboard_id, _dboard_interface
......
82 84
        rx_mux = (((rx_mux >> 0) & 0x3) << 2) | (((rx_mux >> 2) & 0x3) << 0);
83 85
    }
84 86

  
85
    this->poke32(FR_DSP_RX_MUX, rx_mux);
87
    _iface->poke32(FR_DSP_RX_MUX, rx_mux);
86 88
}
87 89

  
88 90
void usrp2_impl::update_tx_mux_config(void){
......
95 97
        tx_mux = (((tx_mux >> 0) & 0x1) << 1) | (((tx_mux >> 1) & 0x1) << 0);
96 98
    }
97 99

  
98
    this->poke32(FR_DSP_TX_MUX, tx_mux);
100
    _iface->poke32(FR_DSP_TX_MUX, tx_mux);
99 101
}
100 102

  
101 103
/***********************************************************************
/dev/null
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 "usrp2_regs.hpp"
20
#include <uhd/types/dict.hpp>
21
#include <uhd/utils/assert.hpp>
22
#include <boost/assign/list_of.hpp>
23
#include <algorithm>
24

  
25
using namespace uhd::usrp;
26

  
27
class usrp2_dboard_interface : public dboard_interface{
28
public:
29
    usrp2_dboard_interface(usrp2_impl *impl);
30
    ~usrp2_dboard_interface(void);
31

  
32
    void write_aux_dac(unit_t, int, int);
33
    int read_aux_adc(unit_t, int);
34

  
35
    void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
36
    void set_gpio_ddr(unit_t, boost::uint16_t);
37
    boost::uint16_t read_gpio(unit_t);
38

  
39
    void write_i2c(int, const byte_vector_t &);
40
    byte_vector_t read_i2c(int, size_t);
41

  
42
    double get_clock_rate(unit_t);
43
    void set_clock_enabled(unit_t, bool);
44
    bool get_clock_enabled(unit_t);
45

  
46
    void write_spi(
47
        unit_t unit,
48
        const spi_config_t &config,
49
        boost::uint32_t data,
50
        size_t num_bits
51
    );
52

  
53
    boost::uint32_t read_write_spi(
54
        unit_t unit,
55
        const spi_config_t &config,
56
        boost::uint32_t data,
57
        size_t num_bits
58
    );
59

  
60
private:
61
    usrp2_impl *_impl;
62
    boost::uint32_t _ddr_shadow;
63
};
64

  
65
/***********************************************************************
66
 * Make Function
67
 **********************************************************************/
68
dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl){
69
    return dboard_interface::sptr(new usrp2_dboard_interface(impl));
70
}
71

  
72
/***********************************************************************
73
 * Structors
74
 **********************************************************************/
75
usrp2_dboard_interface::usrp2_dboard_interface(usrp2_impl *impl){
76
    _impl = impl;
77
    _ddr_shadow = 0;
78

  
79
    //set the selection mux to use atr
80
    boost::uint32_t new_sels = 0x0;
81
    for(size_t i = 0; i < 16; i++){
82
        new_sels |= FRF_GPIO_SEL_ATR << (i*2);
83
    }
84
    _impl->poke32(FR_GPIO_TX_SEL, new_sels);
85
    _impl->poke32(FR_GPIO_RX_SEL, new_sels);
86
}
87

  
88
usrp2_dboard_interface::~usrp2_dboard_interface(void){
89
    /* NOP */
90
}
91

  
92
/***********************************************************************
93
 * Clocks
94
 **********************************************************************/
95
double usrp2_dboard_interface::get_clock_rate(unit_t){
96
    return _impl->get_master_clock_freq();
97
}
98

  
99
void usrp2_dboard_interface::set_clock_enabled(unit_t unit, bool enb){
100
    switch(unit){
101
    case UNIT_RX:
102
        _impl->get_clock_control()->enable_rx_dboard_clock(enb);
103
        return;
104
    case UNIT_TX:
105
        _impl->get_clock_control()->enable_tx_dboard_clock(enb);
106
        return;
107
    }
108
}
109

  
110
/***********************************************************************
111
 * GPIO
112
 **********************************************************************/
113
static int unit_to_shift(dboard_interface::unit_t unit){
114
    switch(unit){
115
    case dboard_interface::UNIT_RX: return 0;
116
    case dboard_interface::UNIT_TX: return 16;
117
    }
118
    throw std::runtime_error("unknown unit type");
119
}
120

  
121
void usrp2_dboard_interface::set_gpio_ddr(unit_t unit, boost::uint16_t value){
122
    _ddr_shadow = \
123
        (_ddr_shadow & ~(0xffff << unit_to_shift(unit))) |
124
        (boost::uint32_t(value) << unit_to_shift(unit));
125
    _impl->poke32(FR_GPIO_DDR, _ddr_shadow);
126
}
127

  
128
boost::uint16_t usrp2_dboard_interface::read_gpio(unit_t unit){
129
    return boost::uint16_t(_impl->peek32(FR_GPIO_IO) >> unit_to_shift(unit));
130
}
131

  
132
void usrp2_dboard_interface::set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){
133
    //define mapping of unit to atr regs to register address
134
    static const uhd::dict<
135
        unit_t, uhd::dict<atr_reg_t, boost::uint32_t>
136
    > unit_to_atr_to_addr = boost::assign::map_list_of
137
        (UNIT_RX, boost::assign::map_list_of
138
            (ATR_REG_IDLE,        FR_ATR_IDLE_RXSIDE)
139
            (ATR_REG_TX_ONLY,     FR_ATR_INTX_RXSIDE)
140
            (ATR_REG_RX_ONLY,     FR_ATR_INRX_RXSIDE)
141
            (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_RXSIDE)
142
        )
143
        (UNIT_TX, boost::assign::map_list_of
144
            (ATR_REG_IDLE,        FR_ATR_IDLE_TXSIDE)
145
            (ATR_REG_TX_ONLY,     FR_ATR_INTX_TXSIDE)
146
            (ATR_REG_RX_ONLY,     FR_ATR_INRX_TXSIDE)
147
            (ATR_REG_FULL_DUPLEX, FR_ATR_FULL_TXSIDE)
148
        )
149
    ;
150
    _impl->poke16(unit_to_atr_to_addr[unit][atr], value);
151
}
152

  
153
/***********************************************************************
154
 * SPI
155
 **********************************************************************/
156
/*!
157
 * Static function to convert a unit type enum
158
 * to an over-the-wire value for the spi device.
159
 * \param unit the dboard interface unit type enum
160
 * \return an over the wire representation
161
 */
162
static boost::uint8_t unit_to_otw_spi_dev(dboard_interface::unit_t unit){
163
    switch(unit){
164
    case dboard_interface::UNIT_TX: return SPI_SS_TX_DB;
165
    case dboard_interface::UNIT_RX: return SPI_SS_RX_DB;
166
    }
167
    throw std::invalid_argument("unknown unit type");
168
}
169

  
170
void usrp2_dboard_interface::write_spi(
171
    unit_t unit,
172
    const spi_config_t &config,
173
    boost::uint32_t data,
174
    size_t num_bits
175
){
176
    _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, false /*no rb*/);
177
}
178

  
179
boost::uint32_t usrp2_dboard_interface::read_write_spi(
180
    unit_t unit,
181
    const spi_config_t &config,
182
    boost::uint32_t data,
183
    size_t num_bits
184
){
185
    return _impl->transact_spi(unit_to_otw_spi_dev(unit), config, data, num_bits, true /*rb*/);
186
}
187

  
188
/***********************************************************************
189
 * I2C
190
 **********************************************************************/
191
void usrp2_dboard_interface::write_i2c(int i2c_addr, const byte_vector_t &buf){
192
    //setup the out data
193
    usrp2_ctrl_data_t out_data;
194
    out_data.id = htonl(USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO);
195
    out_data.data.i2c_args.addr = i2c_addr;
196
    out_data.data.i2c_args.bytes = buf.size();
197

  
198
    //limitation of i2c transaction size
199
    ASSERT_THROW(buf.size() <= sizeof(out_data.data.i2c_args.data));
200

  
201
    //copy in the data
202
    std::copy(buf.begin(), buf.end(), out_data.data.i2c_args.data);
203

  
204
    //send and recv
205
    usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data);
206
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE);
207
}
208

  
209
dboard_interface::byte_vector_t usrp2_dboard_interface::read_i2c(int i2c_addr, size_t num_bytes){
210
    //setup the out data
211
    usrp2_ctrl_data_t out_data;
212
    out_data.id = htonl(USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO);
213
    out_data.data.i2c_args.addr = i2c_addr;
214
    out_data.data.i2c_args.bytes = num_bytes;
215

  
216
    //limitation of i2c transaction size
217
    ASSERT_THROW(num_bytes <= sizeof(out_data.data.i2c_args.data));
218

  
219
    //send and recv
220
    usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data);
221
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE);
222
    ASSERT_THROW(in_data.data.i2c_args.addr = num_bytes);
223

  
224
    //copy out the data
225
    byte_vector_t result(num_bytes);
226
    std::copy(in_data.data.i2c_args.data, in_data.data.i2c_args.data + num_bytes, result.begin());
227
    return result;
228
}
229

  
230
/***********************************************************************
231
 * Aux DAX/ADC
232
 **********************************************************************/
233
/*!
234
 * Static function to convert a unit type enum
235
 * to an over-the-wire value for the usrp2 control.
236
 * \param unit the dboard interface unit type enum
237
 * \return an over the wire representation
238
 */
239
static boost::uint8_t unit_to_otw(dboard_interface::unit_t unit){
240
    switch(unit){
241
    case dboard_interface::UNIT_TX: return USRP2_DIR_TX;
242
    case dboard_interface::UNIT_RX: return USRP2_DIR_RX;
243
    }
244
    throw std::invalid_argument("unknown unit type");
245
}
246

  
247
void usrp2_dboard_interface::write_aux_dac(unit_t unit, int which, int value){
248
    //setup the out data
249
    usrp2_ctrl_data_t out_data;
250
    out_data.id = htonl(USRP2_CTRL_ID_WRITE_THIS_TO_THE_AUX_DAC_BRO);
251
    out_data.data.aux_args.dir = unit_to_otw(unit);
252
    out_data.data.aux_args.which = which;
253
    out_data.data.aux_args.value = htonl(value);
254

  
255
    //send and recv
256
    usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data);
257
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_DAC_DUDE);
258
}
259

  
260
int usrp2_dboard_interface::read_aux_adc(unit_t unit, int which){
261
    //setup the out data
262
    usrp2_ctrl_data_t out_data;
263
    out_data.id = htonl(USRP2_CTRL_ID_READ_FROM_THIS_AUX_ADC_BRO);
264
    out_data.data.aux_args.dir = unit_to_otw(unit);
265
    out_data.data.aux_args.which = which;
266

  
267
    //send and recv
268
    usrp2_ctrl_data_t in_data = _impl->ctrl_send_and_recv(out_data);
269
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_DONE_WITH_THAT_AUX_ADC_DUDE);
270
    return ntohl(in_data.data.aux_args.value);
271
}
b/host/lib/usrp/usrp2/dsp_impl.cpp
20 20
#include <uhd/usrp/dsp_props.hpp>
21 21
#include <uhd/utils/assert.hpp>
22 22
#include <boost/format.hpp>
23
#include <boost/bind.hpp>
23 24
#include <boost/assign/list_of.hpp>
24 25
#include <boost/math/special_functions/round.hpp>
25 26

  
......
82 83

  
83 84
void usrp2_impl::update_ddc_config(void){
84 85
    //set the decimation
85
    this->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim);
86
    _iface->poke32(FR_DSP_RX_DECIM_RATE, _ddc_decim);
86 87

  
87 88
    //set the scaling
88 89
    static const boost::int16_t default_rx_scale_iq = 1024;
89
    this->poke32(FR_DSP_RX_SCALE_IQ,
90
    _iface->poke32(FR_DSP_RX_SCALE_IQ,
90 91
        calculate_iq_scale_word(default_rx_scale_iq, default_rx_scale_iq)
91 92
    );
92 93
}
......
126 127
            ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
127 128
            ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
128 129
            _ddc_freq = new_freq; //shadow
129
            this->poke32(FR_DSP_RX_FREQ,
130
            _iface->poke32(FR_DSP_RX_FREQ,
130 131
                calculate_freq_word_and_update_actual_freq(_ddc_freq, get_master_clock_freq())
131 132
            );
132 133
        }
......
170 171
    boost::int16_t scale = rint((4096*std::pow(2, ceil(log2(interp_cubed))))/(1.65*interp_cubed));
171 172

  
172 173
    //set the interpolation
173
    this->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim);
174
    _iface->poke32(FR_DSP_TX_INTERP_RATE, _ddc_decim);
174 175

  
175 176
    //set the scaling
176
    this->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale));
177
    _iface->poke32(FR_DSP_TX_SCALE_IQ, calculate_iq_scale_word(scale, scale));
177 178
}
178 179

  
179 180
/***********************************************************************
......
211 212
            ASSERT_THROW(new_freq <= get_master_clock_freq()/2.0);
212 213
            ASSERT_THROW(new_freq >= -get_master_clock_freq()/2.0);
213 214
            _duc_freq = new_freq; //shadow
214
            this->poke32(FR_DSP_TX_FREQ,
215
            _iface->poke32(FR_DSP_TX_FREQ,
215 216
                calculate_freq_word_and_update_actual_freq(_duc_freq, get_master_clock_freq())
216 217
            );
217 218
        }
b/host/lib/usrp/usrp2/io_impl.cpp
18 18
#include "usrp2_impl.hpp"
19 19
#include <uhd/transport/convert_types.hpp>
20 20
#include <boost/format.hpp>
21
#include <boost/asio.hpp> //htonl and ntohl
21 22
#include <iostream>
22 23

  
23 24
using namespace uhd;
b/host/lib/usrp/usrp2/mboard_impl.cpp
22 22
#include <uhd/utils/assert.hpp>
23 23
#include <uhd/types/mac_addr.hpp>
24 24
#include <uhd/types/dict.hpp>
25
#include <boost/bind.hpp>
26
#include <boost/asio.hpp> //htonl and ntohl
27
#include <boost/assign/list_of.hpp>
25 28

  
26 29
using namespace uhd;
27 30
using namespace uhd::usrp;
......
35 38
        boost::bind(&usrp2_impl::mboard_set, this, _1, _2)
36 39
    );
37 40

  
38
    _clock_control = clock_control::make_ad9510(this);
41
    _clk_ctrl = clock_control::make_ad9510(_iface);
39 42

  
40 43
    //setup the ad9777 dac
41 44
    ad9777_regs_t ad9777_regs;
......
58 61
    //write all regs
59 62
    for(boost::uint8_t addr = 0; addr <= 0xC; addr++){
60 63
        boost::uint16_t data = ad9777_regs.get_write_reg(addr);
61
        this->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/);
64
        _iface->transact_spi(SPI_SS_AD9777, spi_config_t::EDGE_RISE, data, 16, false /*no rb*/);
62 65
    }
63 66
}
64 67

  
65
clock_control::sptr usrp2_impl::get_clock_control(void){
66
    return _clock_control;
67
}
68

  
69 68
void usrp2_impl::init_clock_config(void){
70 69
    //setup the clock configuration settings
71 70
    _clock_config.ref_source = clock_config_t::REF_INT;
......
94 93
    }
95 94

  
96 95
    //set the pps flags
97
    this->poke32(FR_TIME64_FLAGS, pps_flags);
96
    _iface->poke32(FR_TIME64_FLAGS, pps_flags);
98 97

  
99 98
    //clock source ref 10mhz
100 99
    switch(_clock_config.ref_source){
101
    case clock_config_t::REF_INT : this->poke32(FR_CLOCK_CONTROL, 0x10); break;
102
    case clock_config_t::REF_SMA : this->poke32(FR_CLOCK_CONTROL, 0x1C); break;
103
    case clock_config_t::REF_MIMO: this->poke32(FR_CLOCK_CONTROL, 0x15); break;
100
    case clock_config_t::REF_INT : _iface->poke32(FR_CLOCK_CONTROL, 0x10); break;
101
    case clock_config_t::REF_SMA : _iface->poke32(FR_CLOCK_CONTROL, 0x1C); break;
102
    case clock_config_t::REF_MIMO: _iface->poke32(FR_CLOCK_CONTROL, 0x15); break;
104 103
    }
105 104

  
106 105
    //clock source ref 10mhz
107 106
    bool use_external = _clock_config.ref_source != clock_config_t::REF_INT;
108
    this->get_clock_control()->enable_external_ref(use_external);
107
    _clk_ctrl->enable_external_ref(use_external);
109 108
}
110 109

  
111 110
void usrp2_impl::set_time_spec(const time_spec_t &time_spec, bool now){
112 111
    //set ticks and seconds
113
    this->poke32(FR_TIME64_SECS, time_spec.secs);
114
    this->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq()));
112
    _iface->poke32(FR_TIME64_SECS, time_spec.secs);
113
    _iface->poke32(FR_TIME64_TICKS, time_spec.get_ticks(get_master_clock_freq()));
115 114

  
116 115
    //set the register to latch it all in
117 116
    boost::uint32_t imm_flags = (now)? FRF_TIME64_LATCH_NOW : FRF_TIME64_LATCH_NEXT_PPS;
118
    this->poke32(FR_TIME64_IMM, imm_flags);
117
    _iface->poke32(FR_TIME64_IMM, imm_flags);
119 118
}
120 119

  
121 120
void usrp2_impl::issue_ddc_stream_cmd(const stream_cmd_t &stream_cmd){
......
151 150
    }
152 151

  
153 152
    //send and recv
154
    usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
153
    usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
155 154
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_GOT_THAT_STREAM_COMMAND_DUDE);
156 155
}
157 156

  
......
170 169
            out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO);
171 170

  
172 171
            //send and recv
173
            usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
172
            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
174 173
            ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
175 174

  
176 175
            //extract the address
......
184 183
            out_data.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO);
185 184

  
186 185
            //send and recv
187
            usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
186
            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
188 187
            ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE);
189 188

  
190 189
            //extract the address
......
272 271
            std::copy(mac_addr.to_bytes(), mac_addr.to_bytes()+mac_addr_t::hlen, out_data.data.mac_addr);
273 272

  
274 273
            //send and recv
275
            usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
274
            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
276 275
            ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE);
277 276
            return;
278 277
        }
......
284 283
            out_data.data.ip_addr = htonl(boost::asio::ip::address_v4::from_string(val.as<std::string>()).to_ulong());
285 284

  
286 285
            //send and recv
287
            usrp2_ctrl_data_t in_data = ctrl_send_and_recv(out_data);
286
            usrp2_ctrl_data_t in_data = _iface->ctrl_send_and_recv(out_data);
288 287
            ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE);
289 288
            return;
290 289
        }
b/host/lib/usrp/usrp2/usrp2_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 "usrp2_iface.hpp"
19
#include <uhd/utils/assert.hpp>
20
#include <uhd/types/dict.hpp>
21
#include <boost/thread.hpp>
22
#include <boost/asio.hpp> //used for htonl and ntohl
23
#include <boost/assign/list_of.hpp>
24
#include <stdexcept>
25

  
26
using namespace uhd;
27
using namespace uhd::usrp;
28

  
29
class usrp2_iface_impl : public usrp2_iface{
30
public:
31
/***********************************************************************
32
 * Structors
33
 **********************************************************************/
34
    usrp2_iface_impl(transport::udp_simple::sptr ctrl_transport){
35
        _ctrl_transport = ctrl_transport;
36
    }
37

  
38
    ~usrp2_iface_impl(void){
39
        /* NOP */
40
    }
41

  
42
/***********************************************************************
43
 * Peek and Poke
44
 **********************************************************************/
45
    void poke32(boost::uint32_t addr, boost::uint32_t data){
46
        return this->poke<boost::uint32_t>(addr, data);
47
    }
48

  
49
    boost::uint32_t peek32(boost::uint32_t addr){
50
        return this->peek<boost::uint32_t>(addr);
51
    }
52

  
53
    void poke16(boost::uint32_t addr, boost::uint16_t data){
54
        return this->poke<boost::uint16_t>(addr, data);
55
    }
56

  
57
    boost::uint16_t peek16(boost::uint32_t addr){
58
        return this->peek<boost::uint16_t>(addr);
59
    }
60

  
61
/***********************************************************************
62
 * SPI
63
 **********************************************************************/
64
    boost::uint32_t transact_spi(
65
        int which_slave,
66
        const spi_config_t &config,
67
        boost::uint32_t data,
68
        size_t num_bits,
69
        bool readback
70
    ){
71
        static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of
72
            (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE)
73
            (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL)
74
        ;
75

  
76
        //setup the out data
77
        usrp2_ctrl_data_t out_data;
78
        out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO);
79
        out_data.data.spi_args.dev = which_slave;
80
        out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge];
81
        out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge];
82
        out_data.data.spi_args.readback = (readback)? 1 : 0;
83
        out_data.data.spi_args.num_bits = num_bits;
84
        out_data.data.spi_args.data = htonl(data);
85

  
86
        //send and recv
87
        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
88
        ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
89

  
90
        return ntohl(out_data.data.spi_args.data);
91
    }
92

  
93
/***********************************************************************
94
 * Send/Recv over control
95
 **********************************************************************/
96
    usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){
97
        boost::mutex::scoped_lock lock(_ctrl_mutex);
98

  
99
        //fill in the seq number and send
100
        usrp2_ctrl_data_t out_copy = out_data;
101
        out_copy.seq = htonl(++_ctrl_seq_num);
102
        _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t)));
103

  
104
        //loop until we get the packet or timeout
105
        while(true){
106
            usrp2_ctrl_data_t in_data;
107
            size_t len = _ctrl_transport->recv(boost::asio::buffer(&in_data, sizeof(in_data)));
108
            if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){
109
                return in_data;
110
            }
111
            if (len == 0) break; //timeout
112
            //didnt get seq or bad packet, continue looking...
113
        }
114
        throw std::runtime_error("usrp2 no control response");
115
    }
116

  
117
/***********************************************************************
118
 * Master Clock! Ahhhhh
119
 **********************************************************************/
120
    double get_master_clock_freq(void){
121
        return 100e6;
122
    }
123

  
124
private:
125
    //this lovely lady makes it all possible
126
    transport::udp_simple::sptr _ctrl_transport;
127

  
128
    //used in send/recv
129
    boost::mutex _ctrl_mutex;
130
    boost::uint32_t _ctrl_seq_num;
131

  
132
/***********************************************************************
133
 * Private Templated Peek and Poke
134
 **********************************************************************/
135
    template <class T> void poke(boost::uint32_t addr, T data){
136
        //setup the out data
137
        usrp2_ctrl_data_t out_data;
138
        out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO);
139
        out_data.data.poke_args.addr = htonl(addr);
140
        out_data.data.poke_args.data = htonl(boost::uint32_t(data));
141
        out_data.data.poke_args.num_bytes = sizeof(T);
142

  
143
        //send and recv
144
        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
145
        ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE);
146
    }
147

  
148
    template <class T> T peek(boost::uint32_t addr){
149
        //setup the out data
150
        usrp2_ctrl_data_t out_data;
151
        out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO);
152
        out_data.data.poke_args.addr = htonl(addr);
153
        out_data.data.poke_args.num_bytes = sizeof(T);
154

  
155
        //send and recv
156
        usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
157
        ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE);
158
        return T(ntohl(out_data.data.poke_args.data));
159
    }
160

  
161
};
162

  
163
/***********************************************************************
164
 * Public make function for usrp2 interface
165
 **********************************************************************/
166
usrp2_iface::sptr usrp2_iface::make(transport::udp_simple::sptr ctrl_transport){
167
    return usrp2_iface::sptr(new usrp2_iface_impl(ctrl_transport));
168
}
b/host/lib/usrp/usrp2/usrp2_iface.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_USRP2_IFACE_HPP
19
#define INCLUDED_USRP2_IFACE_HPP
20

  
21
#include <uhd/transport/udp_simple.hpp>
22
#include <uhd/usrp/dboard_interface.hpp> //spi config
23
#include <boost/shared_ptr.hpp>
24
#include <boost/utility.hpp>
25
#include <boost/cstdint.hpp>
26
#include "fw_common.h"
27

  
28
/*!
29
 * The usrp2 interface class:
30
 * Provides a set of functions to implementation layer.
31
 * Including spi, peek, poke, control...
32
 */
33
class usrp2_iface : boost::noncopyable{
34
public:
35
    typedef boost::shared_ptr<usrp2_iface> sptr;
36

  
37
    /*!
38
     * Make a new usrp2 interface with the control transport.
39
     * \param ctrl_transport the udp transport object
40
     * \return a new usrp2 interface object
41
     */
42
    static sptr make(uhd::transport::udp_simple::sptr ctrl_transport);
43

  
44
    /*!
45
     * Perform a control transaction.
46
     * \param data a control data struct
47
     * \return the result control data
48
     */
49
    virtual usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &data) = 0;
50

  
51
    /*!
52
     * Write a register (32 bits)
53
     * \param addr the address
54
     * \param data the 32bit data
55
     */
56
    virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0;
57

  
58
    /*!
59
     * Read a register (32 bits)
60
     * \param addr the address
61
     * \return the 32bit data
62
     */
63
    virtual boost::uint32_t peek32(boost::uint32_t addr) = 0;
64

  
65
    /*!
66
     * Write a register (16 bits)
67
     * \param addr the address
68
     * \param data the 16bit data
69
     */
70
    virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0;
71

  
72
    /*!
73
     * Read a register (16 bits)
74
     * \param addr the address
75
     * \return the 16bit data
76
     */
77
    virtual boost::uint16_t peek16(boost::uint32_t addr) = 0;
78

  
79
    /*!
80
     * Perform an spi transaction.
81
     * \param which_slave the slave device number
82
     * \param config spi config args
83
     * \param data the bits to write
84
     * \param num_bits how many bits in data
85
     * \param readback true to readback a value
86
     * \return spi data if readback set
87
     */
88
    virtual boost::uint32_t transact_spi(
89
        int which_slave,
90
        const uhd::usrp::spi_config_t &config,
91
        boost::uint32_t data,
92
        size_t num_bits,
93
        bool readback
94
    ) = 0;
95

  
96
    /*!
97
     * Get the master clock frequency.
98
     * \return the frequency in Hz
99
     */
100
    virtual double get_master_clock_freq(void) = 0;
101
};
102

  
103
#endif /* INCLUDED_USRP2_IFACE_HPP */
b/host/lib/usrp/usrp2/usrp2_impl.cpp
17 17

  
18 18
#include "usrp2_impl.hpp"
19 19
#include <uhd/transport/if_addrs.hpp>
20
#include <uhd/transport/udp_simple.hpp>
20 21
#include <uhd/usrp/device_props.hpp>
21 22
#include <uhd/utils/assert.hpp>
22 23
#include <uhd/utils/static.hpp>
......
24 25
#include <boost/format.hpp>
25 26
#include <boost/foreach.hpp>
26 27
#include <boost/bind.hpp>
28
#include <boost/asio.hpp> //htonl and ntohl
27 29
#include <iostream>
28 30

  
29 31
using namespace uhd;
......
61 63
    }
62 64

  
63 65
    //create a udp transport to communicate
64
    //TODO if an addr is not provided, search all interfaces?
65 66
    std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT);
66 67
    udp_simple::sptr udp_transport = udp_simple::make_broadcast(
67 68
        hint["addr"], ctrl_port
......
128 129
    udp_simple::sptr ctrl_transport,
129 130
    udp_zero_copy::sptr data_transport
130 131
){
131
    _ctrl_transport = ctrl_transport;
132 132
    _data_transport = data_transport;
133 133

  
134
    //make a new interface for usrp2 stuff
135
    _iface = usrp2_iface::make(ctrl_transport);
136

  
134 137
    //load the allowed decim/interp rates
135 138
    //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
136 139
    _allowed_decim_and_interp_rates.clear();
......
169 172
}
170 173

  
171 174
/***********************************************************************
172
 * Misc Access Methods
173
 **********************************************************************/
174
double usrp2_impl::get_master_clock_freq(void){
175
    return 100e6;
176
}
177

  
178
template <class T> void impl_poke(usrp2_impl *impl, boost::uint32_t addr, T data){
179
    //setup the out data
180
    usrp2_ctrl_data_t out_data;
181
    out_data.id = htonl(USRP2_CTRL_ID_POKE_THIS_REGISTER_FOR_ME_BRO);
182
    out_data.data.poke_args.addr = htonl(addr);
183
    out_data.data.poke_args.data = htonl(boost::uint32_t(data));
184
    out_data.data.poke_args.num_bytes = sizeof(T);
185

  
186
    //send and recv
187
    usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data);
188
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_POKED_REGISTER_SO_BAD_DUDE);
189
}
190

  
191
template <class T> T impl_peek(usrp2_impl *impl, boost::uint32_t addr){
192
    //setup the out data
193
    usrp2_ctrl_data_t out_data;
194
    out_data.id = htonl(USRP2_CTRL_ID_PEEK_AT_THIS_REGISTER_FOR_ME_BRO);
195
    out_data.data.poke_args.addr = htonl(addr);
196
    out_data.data.poke_args.num_bytes = sizeof(T);
197

  
198
    //send and recv
199
    usrp2_ctrl_data_t in_data = impl->ctrl_send_and_recv(out_data);
200
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_WOAH_I_DEFINITELY_PEEKED_IT_DUDE);
201
    return T(ntohl(out_data.data.poke_args.data));
202
}
203

  
204

  
205
void usrp2_impl::poke32(boost::uint32_t addr, boost::uint32_t data){
206
    return impl_poke<boost::uint32_t>(this, addr, data);
207
}
208

  
209
boost::uint32_t usrp2_impl::peek32(boost::uint32_t addr){
210
    return impl_peek<boost::uint32_t>(this, addr);
211
}
212

  
213
void usrp2_impl::poke16(boost::uint32_t addr, boost::uint16_t data){
214
    return impl_poke<boost::uint16_t>(this, addr, data);
215
}
216

  
217
boost::uint16_t usrp2_impl::peek16(boost::uint32_t addr){
218
    return impl_peek<boost::uint16_t>(this, addr);
219
}
220

  
221
boost::uint32_t usrp2_impl::transact_spi(
222
    int which_slave,
223
    const spi_config_t &config,
224
    boost::uint32_t data,
225
    size_t num_bits,
226
    bool readback
227
){
228
    static const uhd::dict<spi_config_t::edge_t, int> spi_edge_to_otw = boost::assign::map_list_of
229
        (spi_config_t::EDGE_RISE, USRP2_CLK_EDGE_RISE)
230
        (spi_config_t::EDGE_FALL, USRP2_CLK_EDGE_FALL)
231
    ;
232

  
233
    //setup the out data
234
    usrp2_ctrl_data_t out_data;
235
    out_data.id = htonl(USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO);
236
    out_data.data.spi_args.dev = which_slave;
237
    out_data.data.spi_args.miso_edge = spi_edge_to_otw[config.miso_edge];
238
    out_data.data.spi_args.mosi_edge = spi_edge_to_otw[config.mosi_edge];
239
    out_data.data.spi_args.readback = (readback)? 1 : 0;
240
    out_data.data.spi_args.num_bits = num_bits;
241
    out_data.data.spi_args.data = htonl(data);
242

  
243
    //send and recv
244
    usrp2_ctrl_data_t in_data = this->ctrl_send_and_recv(out_data);
245
    ASSERT_THROW(htonl(in_data.id) == USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE);
246

  
247
    return ntohl(out_data.data.spi_args.data);
248
}
249

  
250
/***********************************************************************
251
 * Control Send/Recv
252
 **********************************************************************/
253
usrp2_ctrl_data_t usrp2_impl::ctrl_send_and_recv(const usrp2_ctrl_data_t &out_data){
254
    boost::mutex::scoped_lock lock(_ctrl_mutex);
255

  
256
    //fill in the seq number and send
257
    usrp2_ctrl_data_t out_copy = out_data;
258
    out_copy.seq = htonl(++_ctrl_seq_num);
259
    _ctrl_transport->send(boost::asio::buffer(&out_copy, sizeof(usrp2_ctrl_data_t)));
260

  
261
    //loop until we get the packet or timeout
262
    while(true){
263
        usrp2_ctrl_data_t in_data;
264
        size_t len = _ctrl_transport->recv(asio::buffer(&in_data, sizeof(in_data)));
265
        if (len >= sizeof(usrp2_ctrl_data_t) and ntohl(in_data.seq) == _ctrl_seq_num){
266
            return in_data;
267
        }
268
        if (len == 0) break; //timeout
269
        //didnt get seq or bad packet, continue looking...
270
    }
271
    throw std::runtime_error("usrp2 no control response");
272
}
273

  
274
/***********************************************************************
275 175
 * Device Properties
276 176
 **********************************************************************/
277 177
void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
b/host/lib/usrp/usrp2/usrp2_impl.hpp
18 18
#ifndef INCLUDED_USRP2_IMPL_HPP
19 19
#define INCLUDED_USRP2_IMPL_HPP
20 20

  
21
#include "usrp2_iface.hpp"
21 22
#include "clock_control.hpp"
22 23
#include <uhd/usrp/usrp2.hpp>
23 24
#include <uhd/types/dict.hpp>
24 25
#include <uhd/types/otw_type.hpp>
25 26
#include <uhd/types/stream_cmd.hpp>
26 27
#include <uhd/types/clock_config.hpp>
27
#include <boost/asio.hpp>
28
#include <boost/thread.hpp>
29 28
#include <boost/shared_ptr.hpp>
30 29
#include <boost/function.hpp>
31
#include <boost/assign/list_of.hpp>
32 30
#include <uhd/transport/vrt.hpp>
33
#include <uhd/transport/udp_simple.hpp>
34 31
#include <uhd/transport/udp_zero_copy.hpp>
35 32
#include <uhd/usrp/dboard_manager.hpp>
36
#include "fw_common.h"
37

  
38
class usrp2_impl; //dummy class declaration
39 33

  
40 34
/*!
41 35
 * Make a usrp2 dboard interface.
42
 * \param impl a pointer to the usrp2 impl object
36
 * \param iface the usrp2 interface object
37
 * \param clk_ctrl the clock control object
43 38
 * \return a sptr to a new dboard interface
44 39
 */
45
uhd::usrp::dboard_interface::sptr make_usrp2_dboard_interface(usrp2_impl *impl);
40
uhd::usrp::dboard_interface::sptr make_usrp2_dboard_iface(
41
    usrp2_iface::sptr iface,
42
    clock_control::sptr clk_ctrl
43
);
46 44

  
47 45
/*!
48 46
 * Simple wax obj proxy class:
......
101 99

  
102 100
    ~usrp2_impl(void);
103 101

  
104
    //performs a control transaction
105
    usrp2_ctrl_data_t ctrl_send_and_recv(const usrp2_ctrl_data_t &);
106

  
107
    //peek and poke registers
108
    void poke32(boost::uint32_t addr, boost::uint32_t data);
109
    boost::uint32_t peek32(boost::uint32_t addr);
110

  
111
    void poke16(boost::uint32_t addr, boost::uint16_t data);
112
    boost::uint16_t peek16(boost::uint32_t addr);
113

  
114
    //clock control
115
    clock_control::sptr get_clock_control(void);
116

  
117
    //spi read and write
118
    boost::uint32_t transact_spi(
119
        int which_slave,
120
        const uhd::usrp::spi_config_t &config,
121
        boost::uint32_t data,
122
        size_t num_bits,
123
        bool readback
124
    );
125

  
126
    //misc access methods
127
    double get_master_clock_freq(void);
128

  
129 102
    //the io interface
130 103
    size_t send(const boost::asio::const_buffer &, const uhd::tx_metadata_t &, const uhd::io_type_t &);
131 104
    size_t recv(const boost::asio::mutable_buffer &, uhd::rx_metadata_t &, const uhd::io_type_t &);
132 105

  
133 106
private:
107
    double get_master_clock_freq(void){
108
        return _iface->get_master_clock_freq();
109
    }
110

  
134 111
    //device properties interface
135 112
    void get(const wax::obj &, wax::obj &);
136 113
    void set(const wax::obj &, const wax::obj &);
137
    clock_control::sptr _clock_control;
114

  
115
    //interfaces
116
    clock_control::sptr _clk_ctrl;
117
    usrp2_iface::sptr _iface;
138 118

  
139 119
    //the raw io interface (samples are in the usrp2 native format)
140 120
    void recv_raw(uhd::rx_metadata_t &);
......
158 138
    void io_init(void);
159 139

  
160 140
    //udp transports for control and data
161
    uhd::transport::udp_simple::sptr _ctrl_transport;
162 141
    uhd::transport::udp_zero_copy::sptr _data_transport;
163 142

  
164
    //private vars for dealing with send/recv control
165
    boost::uint32_t _ctrl_seq_num;
166
    boost::mutex _ctrl_mutex;
167

  
168 143
    //methods and shadows for clock configuration
169 144
    uhd::clock_config_t _clock_config;
170 145
    void init_clock_config(void);

Also available in: Unified diff