1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_DEVICE_H
#define INCLUDED_AD9361_DEVICE_H
#include <ad9361_client.h>
#include <boost/noncopyable.hpp>
namespace uhd { namespace usrp {
class ad9361_device_t : public boost::noncopyable
{
public:
enum direction_t { RX, TX };
enum chain_t { CHAIN_1, CHAIN_2 };
ad9361_device_t(ad9361_params::sptr client, ad9361_io::sptr io_iface) :
_client_params(client), _io_iface(io_iface) {}
/* Initialize the AD9361 codec. */
void initialize();
/* This function sets the RX / TX rate between AD9361 and the FPGA, and
* thus determines the interpolation / decimation required in the FPGA to
* achieve the user's requested rate.
*/
double set_clock_rate(const double req_rate);
/* Set which of the four TX / RX chains provided by AD9361 are active.
*
* AD9361 provides two sets of chains, Side A and Side B. Each side
* provides one TX antenna, and one RX antenna. The B200 maintains the USRP
* standard of providing one antenna connection that is both TX & RX, and
* one that is RX-only - for each chain. Thus, the possible antenna and
* chain selections are:
*
*/
void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2);
/* Tune the RX or TX frequency.
*
* This is the publicly-accessible tune function. It makes sure the tune
* isn't a redundant request, and if not, passes it on to the class's
* internal tune function.
*
* After tuning, it runs any appropriate calibrations. */
double tune(direction_t direction, const double value);
/* Set the gain of RX1, RX2, TX1, or TX2.
*
* Note that the 'value' passed to this function is the actual gain value,
* _not_ the gain index. This is the opposite of the eval software's GUI!
* Also note that the RX chains are done in terms of gain, and the TX chains
* are done in terms of attenuation. */
double set_gain(direction_t direction, chain_t chain, const double value);
/* Make AD9361 output its test tone. */
void output_test_tone();
/* Turn on/off AD9361's TX port --> RX port loopback. */
void data_port_loopback(const bool loopback_enabled);
private: //Methods
void _program_fir_filter(direction_t direction, int num_taps, boost::uint16_t *coeffs);
void _setup_tx_fir(size_t num_taps);
void _setup_rx_fir(size_t num_taps);
void _calibrate_lock_bbpll();
void _calibrate_synth_charge_pumps();
double _calibrate_baseband_rx_analog_filter();
double _calibrate_baseband_tx_analog_filter();
void _calibrate_secondary_tx_filter();
void _calibrate_rx_TIAs();
void _setup_adc();
void _calibrate_baseband_dc_offset();
void _calibrate_rf_dc_offset();
void _calibrate_rx_quadrature();
void _tx_quadrature_cal_routine();
void _calibrate_tx_quadrature();
void _program_mixer_gm_subtable();
void _program_gain_table();
void _setup_gain_control();
void _setup_synth(direction_t direction, double vcorate);
double _tune_bbvco(const double rate);
void _reprogram_gains();
double _tune_helper(direction_t direction, const double value);
double _setup_rates(const double rate);
private: //Members
typedef struct {
boost::uint8_t vcodivs;
boost::uint8_t inputsel;
boost::uint8_t rxfilt;
boost::uint8_t txfilt;
boost::uint8_t bbpll;
boost::uint8_t bbftune_config;
boost::uint8_t bbftune_mode;
} chip_regs_t;
//Interfaces
ad9361_params::sptr _client_params;
ad9361_io::sptr _io_iface;
//Intermediate state
double _rx_freq, _tx_freq, _req_rx_freq, _req_tx_freq;
double _baseband_bw, _bbpll_freq, _adcclock_freq;
double _req_clock_rate, _req_coreclk;
boost::uint16_t _rx_bbf_tunediv;
boost::uint8_t _curr_gain_table;
boost::uint32_t _rx1_gain, _rx2_gain, _tx1_gain, _tx2_gain;
boost::int32_t _tfir_factor;
//Register soft-copies
chip_regs_t _regs;
};
}} //namespace
#endif /* INCLUDED_AD9361_DEVICE_H */
|