Statistics
| Branch: | Tag: | Revision:

root / host / lib / usrp / usrp1 / dboard_iface.cpp @ cc6bbf94

History | View | Annotate | Download (11.7 kB)

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

    
18
#include "usrp1_iface.hpp"
19
#include "usrp1_impl.hpp"
20
#include "fpga_regs_common.h"
21
#include "usrp_spi_defs.h"
22
#include "clock_ctrl.hpp"
23
#include "codec_ctrl.hpp"
24
#include <uhd/usrp/dboard_iface.hpp>
25
#include <uhd/types/dict.hpp>
26
#include <uhd/utils/assert.hpp>
27
#include <boost/assign/list_of.hpp>
28
#include <iostream>
29

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

    
34
class usrp1_dboard_iface : public dboard_iface {
35
public:
36

    
37
    usrp1_dboard_iface(usrp1_iface::sptr iface,
38
                       usrp1_clock_ctrl::sptr clock,
39
                       usrp1_codec_ctrl::sptr codec,
40
                       usrp1_impl::dboard_slot_t dboard_slot
41
    ){
42
        _iface = iface;
43
        _clock = clock;
44
        _codec = codec;
45
        _dboard_slot = dboard_slot;
46

    
47
        //init the clock rate shadows
48
        this->set_clock_rate(UNIT_RX, _clock->get_master_clock_freq());
49
        this->set_clock_rate(UNIT_TX, _clock->get_master_clock_freq());
50
    }
51

    
52
    ~usrp1_dboard_iface()
53
    {
54
        /* NOP */
55
    }
56

    
57
    special_props_t get_special_props()
58
    {
59
        special_props_t props;
60
        props.soft_clock_divider = true;
61
        props.mangle_i2c_addrs = (_dboard_slot == usrp1_impl::DBOARD_SLOT_B);
62
        return props;
63
    }
64

    
65
    void write_aux_dac(unit_t, aux_dac_t, float);
66
    float read_aux_adc(unit_t, aux_adc_t);
67

    
68
    void set_pin_ctrl(unit_t, boost::uint16_t);
69
    void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
70
    void set_gpio_ddr(unit_t, boost::uint16_t);
71
    void write_gpio(unit_t, boost::uint16_t);
72
    boost::uint16_t read_gpio(unit_t);
73

    
74
    void write_i2c(boost::uint8_t, const byte_vector_t &);
75
    byte_vector_t read_i2c(boost::uint8_t, size_t);
76

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

    
82
    boost::uint32_t read_write_spi(unit_t unit,
83
                                   const spi_config_t &config,
84
                                   boost::uint32_t data,
85
                                   size_t num_bits);
86

    
87
    void set_clock_rate(unit_t, double);
88
    std::vector<double> get_clock_rates(unit_t);
89
    double get_clock_rate(unit_t);
90
    void set_clock_enabled(unit_t, bool);
91

    
92
private:
93
    usrp1_iface::sptr _iface;
94
    usrp1_clock_ctrl::sptr _clock;
95
    usrp1_codec_ctrl::sptr _codec;
96
    uhd::dict<unit_t, double> _clock_rates;
97
    usrp1_impl::dboard_slot_t _dboard_slot;
98
};
99

    
100
/***********************************************************************
101
 * Make Function
102
 **********************************************************************/
103
dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface,
104
                                           usrp1_clock_ctrl::sptr clock,
105
                                           usrp1_codec_ctrl::sptr codec,
106
                                           dboard_slot_t dboard_slot
107
){
108
    return dboard_iface::sptr(new usrp1_dboard_iface(iface, clock, codec, dboard_slot));
109
}
110

    
111
/***********************************************************************
112
 * Clock Rates
113
 **********************************************************************/
114
void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate)
115
{
116
    _clock_rates[unit] = rate;
117
    switch(unit) {
118
    case UNIT_RX: return _clock->set_rx_dboard_clock_rate(rate);    
119
    case UNIT_TX: return _clock->set_tx_dboard_clock_rate(rate);    
120
    }
121
}
122

    
123
/*
124
 * TODO: if this is a dbsrx return the rate of 4MHZ and set FPGA magic
125
 */
126
std::vector<double> usrp1_dboard_iface::get_clock_rates(unit_t unit)
127
{
128
    switch(unit) {
129
    case UNIT_RX: return _clock->get_rx_dboard_clock_rates();
130
    case UNIT_TX: return _clock->get_tx_dboard_clock_rates();
131
    default: UHD_THROW_INVALID_CODE_PATH();
132
    }
133
}
134

    
135
double usrp1_dboard_iface::get_clock_rate(unit_t unit)
136
{
137
    return _clock_rates[unit];
138
}
139

    
140
void usrp1_dboard_iface::set_clock_enabled(unit_t unit, bool enb)
141
{
142
    switch(unit) {
143
    case UNIT_RX: return _clock->enable_rx_dboard_clock(enb);
144
    case UNIT_TX: return _clock->enable_tx_dboard_clock(enb);
145
    }
146
}
147

    
148
/***********************************************************************
149
 * GPIO
150
 **********************************************************************/
151
void usrp1_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value)
152
{
153
    switch(unit) {
154
    case UNIT_RX:
155
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
156
             _iface->poke32(FR_ATR_MASK_1, value);
157
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
158
             _iface->poke32(FR_ATR_MASK_3, value);
159
        break;
160
    case UNIT_TX:
161
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
162
            _iface->poke32(FR_ATR_MASK_0, value);
163
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
164
            _iface->poke32(FR_ATR_MASK_2, value);
165
        break;
166
    }
167
}
168

    
169
void usrp1_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value)
170
{
171
    switch(unit) {
172
    case UNIT_RX:
173
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
174
            _iface->poke32(FR_OE_1, 0xffff0000 | value);
175
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
176
            _iface->poke32(FR_OE_3, 0xffff0000 | value);
177
        break;
178
    case UNIT_TX:
179
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
180
            _iface->poke32(FR_OE_0, 0xffff0000 | value);
181
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
182
            _iface->poke32(FR_OE_2, 0xffff0000 | value);
183
        break;
184
    }
185
}
186

    
187
void usrp1_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value)
188
{
189
    switch(unit) {
190
    case UNIT_RX:
191
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
192
            _iface->poke32(FR_IO_1, 0xffff0000 | value);
193
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
194
            _iface->poke32(FR_IO_3, 0xffff0000 | value);
195
        break;
196
    case UNIT_TX:
197
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
198
            _iface->poke32(FR_IO_0, 0xffff0000 | value);
199
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
200
            _iface->poke32(FR_IO_2, 0xffff0000 | value);
201
        break;
202
    }
203
}
204

    
205
boost::uint16_t usrp1_dboard_iface::read_gpio(unit_t unit)
206
{
207
    boost::uint32_t out_value;
208

    
209
    if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
210
        out_value = _iface->peek32(1);
211
    else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
212
        out_value = _iface->peek32(2);
213
    else
214
        UHD_THROW_INVALID_CODE_PATH();
215

    
216
    switch(unit) {
217
    case UNIT_RX:
218
        return (boost::uint16_t)((out_value >> 16) & 0x0000ffff);
219
    case UNIT_TX:
220
        return (boost::uint16_t)((out_value >>  0) & 0x0000ffff);
221
    }
222
    UHD_ASSERT_THROW(false);
223
}
224

    
225
void usrp1_dboard_iface::set_atr_reg(unit_t unit,
226
                                     atr_reg_t atr, boost::uint16_t value)
227
{
228
    // Ignore unsupported states
229
    if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX))
230
        return;
231

    
232
    switch(unit) {
233
    case UNIT_RX:
234
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
235
            _iface->poke32(FR_ATR_RXVAL_1, value);
236
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
237
            _iface->poke32(FR_ATR_RXVAL_3, value);
238
        break; 
239
    case UNIT_TX:
240
        if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
241
            _iface->poke32(FR_ATR_TXVAL_0, value);
242
        else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
243
            _iface->poke32(FR_ATR_TXVAL_2, value);
244
        break;
245
    }
246
}
247
/***********************************************************************
248
 * SPI
249
 **********************************************************************/
250
/*!
251
 * Static function to convert a unit type to a spi slave device number.
252
 * \param unit the dboard interface unit type enum
253
 * \param slot the side (A or B) the dboard is attached
254
 * \return the slave device number
255
 */
256
static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit,
257
                                           usrp1_impl::dboard_slot_t slot)
258
{
259
    switch(unit) {
260
    case dboard_iface::UNIT_TX:
261
        if (slot == usrp1_impl::DBOARD_SLOT_A)
262
            return SPI_ENABLE_TX_A; 
263
        else if (slot == usrp1_impl::DBOARD_SLOT_B)
264
            return SPI_ENABLE_TX_B;
265
        else
266
            break;
267
    case dboard_iface::UNIT_RX:
268
        if (slot == usrp1_impl::DBOARD_SLOT_A)
269
            return SPI_ENABLE_RX_A; 
270
        else if (slot == usrp1_impl::DBOARD_SLOT_B)
271
            return SPI_ENABLE_RX_B;
272
        else
273
            break;
274
    }
275
    throw std::invalid_argument("unknown unit type");
276
}
277

    
278
void usrp1_dboard_iface::write_spi(unit_t unit,
279
                                   const spi_config_t &config,
280
                                   boost::uint32_t data,
281
                                   size_t num_bits)
282
{
283
    _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
284
                         config, data, num_bits, false);
285
}
286

    
287
boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit,
288
                                                   const spi_config_t &config,
289
                                                   boost::uint32_t data,
290
                                                   size_t num_bits)
291
{
292
    return _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
293
                                config, data, num_bits, true);
294
}
295

    
296
/***********************************************************************
297
 * I2C
298
 **********************************************************************/
299
void usrp1_dboard_iface::write_i2c(boost::uint8_t addr,
300
                                   const byte_vector_t &bytes)
301
{
302
    return _iface->write_i2c(addr, bytes);
303
}
304

    
305
byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr,
306
                                           size_t num_bytes)
307
{
308
    return _iface->read_i2c(addr, num_bytes);
309
}
310

    
311
/***********************************************************************
312
 * Aux DAX/ADC
313
 **********************************************************************/
314
void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t,
315
                                       aux_dac_t which, float value)
316
{
317
    //same aux dacs for each unit
318
    static const uhd::dict<aux_dac_t, usrp1_codec_ctrl::aux_dac_t>
319
        which_to_aux_dac = map_list_of
320
                                     (AUX_DAC_A, usrp1_codec_ctrl::AUX_DAC_A)
321
                                     (AUX_DAC_B, usrp1_codec_ctrl::AUX_DAC_B)
322
                                     (AUX_DAC_C, usrp1_codec_ctrl::AUX_DAC_C)
323
                                     (AUX_DAC_D, usrp1_codec_ctrl::AUX_DAC_D);
324

    
325
    _codec->write_aux_dac(which_to_aux_dac[which], value);
326
}
327

    
328
float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
329
                                       aux_adc_t which)
330
{
331
    static const
332
    uhd::dict<unit_t, uhd::dict<aux_adc_t, usrp1_codec_ctrl::aux_adc_t> >
333
        unit_to_which_to_aux_adc = map_list_of(UNIT_RX, map_list_of
334
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A1)
335
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B1))
336
                                              (UNIT_TX, map_list_of
337
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A2)
338
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B2));
339

    
340
    return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]);
341
}