Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (11.9 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
    if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX)) {
229
        //TODO probably just ignore these two atr settings because all dboards will try to set them
230
        std::cerr << "error: set_atr_reg(): unsupported state" << std::endl;
231
        return;
232
    }
233

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

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

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

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

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

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

    
327
    _codec->write_aux_dac(which_to_aux_dac[which], value);
328
}
329

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

    
342
    return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]);
343
}