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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
|
//
// Copyright 2011-2012 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Common IO Pins
#define LO_LPF_EN (1 << 15)
#define SYNTH_CE (1 << 3)
#define SYNTH_PDBRF (1 << 2)
#define SYNTH_MUXOUT (1 << 1) // INPUT!!!
#define LOCKDET_MASK (1 << 0) // INPUT!!!
// TX IO Pins
#define TRSW (1 << 14) // 0 = TX, 1 = RX
#define TX_LED_TXRX (1 << 7) // LED for TX Antenna Selection TX/RX
#define TX_LED_LD (1 << 6) // LED for TX Lock Detect
#define DIS_POWER_TX (1 << 5) // on UNIT_TX, 0 powers up TX
#define TX_ENABLE (1 << 4) // on UNIT_TX, 0 disables TX Mixer
// RX IO Pins
#define LNASW (1 << 14) // 0 = TX/RX, 1 = RX2
#define RX_LED_RX1RX2 (1 << 7) // LED for RX Antenna Selection RX1/RX2
#define RX_LED_LD (1 << 6) // LED for RX Lock Detect
#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX
#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband
// RX Attenuator Pins
#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control
#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control
// TX Attenuator Pins
#define TX_ATTN_SHIFT 8 // lsb of TX Attenuator Control
#define TX_ATTN_MASK (63 << TX_ATTN_SHIFT) // valid bits of TX Attenuator Control
// Mixer functions
#define TX_MIXER_ENB (SYNTH_PDBRF|TX_ENABLE)
#define TX_MIXER_DIS 0
#define RX_MIXER_ENB (SYNTH_PDBRF)
#define RX_MIXER_DIS 0
// Pin functions
#define TX_LED_IO (TX_LED_TXRX|TX_LED_LD) // LED gpio lines, pull down for LED
#define TXIO_MASK (LO_LPF_EN|TRSW|SYNTH_CE|SYNTH_PDBRF|TX_ATTN_MASK|DIS_POWER_TX|TX_ENABLE)
#define RX_LED_IO (RX_LED_RX1RX2|RX_LED_LD) // LED gpio lines, pull down for LED
#define RXIO_MASK (LO_LPF_EN|LNASW|SYNTH_CE|SYNTH_PDBRF|RX_ATTN_MASK|DIS_POWER_RX|RX_DISABLE)
// Power functions
#define TX_POWER_UP (SYNTH_CE)
#define TX_POWER_DOWN (DIS_POWER_TX)
#define RX_POWER_UP (SYNTH_CE)
#define RX_POWER_DOWN (DIS_POWER_RX)
// Antenna constants
#define ANT_TX TRSW //the tx line is transmitting
#define ANT_RX 0 //the tx line is receiving
#define ANT_TXRX 0 //the rx line is on txrx
#define ANT_RX2 LNASW //the rx line in on rx2
#define ANT_XX LNASW //dont care how the antenna is set
#include <uhd/types/dict.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/sensors.hpp>
#include <uhd/utils/assert_has.hpp>
#include <uhd/utils/log.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/math/special_functions/round.hpp>
#include <boost/thread.hpp>
using namespace uhd;
using namespace uhd::usrp;
using namespace boost::assign;
/***********************************************************************
* The SBX dboard constants
**********************************************************************/
static const freq_range_t sbx_freq_range(400e6, 4.4e9);
static const freq_range_t cbx_freq_range(1200e6, 6.0e9);
static const freq_range_t sbx_tx_lo_2dbm = list_of
(range_t(0.35e9, 0.37e9))
;
static const freq_range_t sbx_enable_tx_lo_filter = list_of
(range_t(0.4e9, 1.5e9))
;
static const freq_range_t sbx_enable_rx_lo_filter = list_of
(range_t(0.4e9, 1.5e9))
;
static const std::vector<std::string> sbx_tx_antennas = list_of("TX/RX")("CAL");
static const std::vector<std::string> sbx_rx_antennas = list_of("TX/RX")("RX2")("CAL");
static const uhd::dict<std::string, gain_range_t> sbx_tx_gain_ranges = map_list_of
("PGA0", gain_range_t(0, 31.5, double(0.5)))
;
static const uhd::dict<std::string, gain_range_t> sbx_rx_gain_ranges = map_list_of
("PGA0", gain_range_t(0, 31.5, double(0.5)))
;
/***********************************************************************
* The SBX dboard
**********************************************************************/
class sbx_xcvr : public xcvr_dboard_base{
public:
sbx_xcvr(ctor_args_t args);
~sbx_xcvr(void);
protected:
uhd::dict<std::string, double> _tx_gains, _rx_gains;
double _rx_lo_freq, _tx_lo_freq;
std::string _tx_ant, _rx_ant;
bool _rx_lo_lock_cache, _tx_lo_lock_cache;
void set_rx_ant(const std::string &ant);
void set_tx_ant(const std::string &ant);
double set_rx_gain(double gain, const std::string &name);
double set_tx_gain(double gain, const std::string &name);
void update_atr(void);
/*!
* Set the LO frequency for the particular dboard unit.
* \param unit which unit rx or tx
* \param target_freq the desired frequency in Hz
* \return the actual frequency in Hz
*/
virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq);
/*!
* Get the lock detect status of the LO.
* \param unit which unit rx or tx
* \return true for locked
*/
sensor_value_t get_locked(dboard_iface::unit_t unit);
/*!
* Flash the LEDs
*/
void flash_leds(void);
/*!
* Version-agnostic ABC that wraps version-specific implementations of the
* WBX base daughterboard.
*
* This class is an abstract base class, and thus is impossible to
* instantiate.
*/
class sbx_versionx {
public:
sbx_versionx() {}
~sbx_versionx(void) {}
virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0;
protected:
struct adf435x_tuning_constraints {
bool force_frac0;
double ref_doubler_threshold;
double pfd_freq_max;
double band_sel_freq_max;
uhd::range_t rf_divider_range;
uhd::range_t int_range;
};
struct adf435x_tuning_settings {
boost::uint16_t frac_12_bit;
boost::uint16_t int_16_bit;
boost::uint16_t mod_12_bit;
boost::uint16_t r_counter_10_bit;
bool r_doubler_en;
bool r_divide_by_2_en;
boost::uint16_t clock_divider_12_bit;
boost::uint8_t band_select_clock_div;
boost::uint16_t rf_divider;
bool feedback_after_divider;
};
adf435x_tuning_settings _tune_adf435x_synth(
double target_freq,
double ref_freq,
const adf435x_tuning_constraints& constraints,
double& actual_freq);
};
/*!
* Version 3 of the SBX Daughterboard
*/
class sbx_version3 : public sbx_versionx {
public:
sbx_version3(sbx_xcvr *_self_sbx_xcvr);
~sbx_version3(void);
double set_lo_freq(dboard_iface::unit_t unit, double target_freq);
/*! This is the registered instance of the wrapper class, sbx_base. */
sbx_xcvr *self_base;
};
/*!
* Version 4 of the SBX Daughterboard
*
* The only difference in the fourth revision is the ADF4351 vs the ADF4350.
*/
class sbx_version4 : public sbx_versionx {
public:
sbx_version4(sbx_xcvr *_self_sbx_xcvr);
~sbx_version4(void);
double set_lo_freq(dboard_iface::unit_t unit, double target_freq);
/*! This is the registered instance of the wrapper class, sbx_base. */
sbx_xcvr *self_base;
};
/*!
* CBX daughterboard
*
* The only driver difference between SBX and CBX is the MAX2870 vs. ADF435x.
* There is also no LO filter switching required, but the GPIO is left blank
* so we don't worry about it.
*/
class cbx : public sbx_versionx {
public:
cbx(sbx_xcvr *_self_sbx_xcvr);
~cbx(void);
double set_lo_freq(dboard_iface::unit_t unit, double target_freq);
/*! This is the registered instance of the wrapper class, sbx_base. */
sbx_xcvr *self_base;
};
/*!
* Frequency range of the daughterboard; this is set in the constructor
* to correspond either to SBX or CBX.
*/
freq_range_t freq_range;
/*!
* Handle to the version-specific implementation of the SBX.
*
* Since many of this class's functions are dependent on the version of the
* SBX board, this class will instantiate an object of the appropriate
* sbx_version* subclass, and invoke any relevant functions through that
* object. This pointer is set to the proper object at construction time.
*/
typedef boost::shared_ptr<sbx_versionx> sbx_versionx_sptr;
sbx_versionx_sptr db_actual;
};
|