Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.8 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
    void set_gpio_debug(unit_t, int);
73
    boost::uint16_t read_gpio(unit_t);
74

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

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

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

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

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

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

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

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

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

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

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

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

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

    
206
void usrp1_dboard_iface::set_gpio_debug(unit_t, int)
207
{
208
    /* NOP */
209
}
210

    
211
boost::uint16_t usrp1_dboard_iface::read_gpio(unit_t unit)
212
{
213
    boost::uint32_t out_value;
214

    
215
    if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
216
        out_value = _iface->peek32(1);
217
    else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
218
        out_value = _iface->peek32(2);
219
    else
220
        UHD_THROW_INVALID_CODE_PATH();
221

    
222
    switch(unit) {
223
    case UNIT_RX:
224
        return (boost::uint16_t)((out_value >> 16) & 0x0000ffff);
225
    case UNIT_TX:
226
        return (boost::uint16_t)((out_value >>  0) & 0x0000ffff);
227
    }
228
    UHD_ASSERT_THROW(false);
229
}
230

    
231
void usrp1_dboard_iface::set_atr_reg(unit_t unit,
232
                                     atr_reg_t atr, boost::uint16_t value)
233
{
234
    // Ignore unsupported states
235
    if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX))
236
        return;
237

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

    
284
void usrp1_dboard_iface::write_spi(unit_t unit,
285
                                   const spi_config_t &config,
286
                                   boost::uint32_t data,
287
                                   size_t num_bits)
288
{
289
    _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
290
                         config, data, num_bits, false);
291
}
292

    
293
boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit,
294
                                                   const spi_config_t &config,
295
                                                   boost::uint32_t data,
296
                                                   size_t num_bits)
297
{
298
    return _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
299
                                config, data, num_bits, true);
300
}
301

    
302
/***********************************************************************
303
 * I2C
304
 **********************************************************************/
305
void usrp1_dboard_iface::write_i2c(boost::uint8_t addr,
306
                                   const byte_vector_t &bytes)
307
{
308
    return _iface->write_i2c(addr, bytes);
309
}
310

    
311
byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr,
312
                                           size_t num_bytes)
313
{
314
    return _iface->read_i2c(addr, num_bytes);
315
}
316

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

    
331
    _codec->write_aux_dac(which_to_aux_dac[which], value);
332
}
333

    
334
float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
335
                                       aux_adc_t which)
336
{
337
    static const
338
    uhd::dict<unit_t, uhd::dict<aux_adc_t, usrp1_codec_ctrl::aux_adc_t> >
339
        unit_to_which_to_aux_adc = map_list_of(UNIT_RX, map_list_of
340
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A1)
341
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B1))
342
                                              (UNIT_TX, map_list_of
343
                                    (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A2)
344
                                    (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B2));
345

    
346
    return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]);
347
}