2 // Copyright 2008 Free Software Foundation, Inc.
4 // This file is part of GNU Radio
6 // GNU Radio is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either asversion 3, or (at your option)
11 // GNU Radio is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with GNU Radio; see the file COPYING. If not, write to
18 // the Free Software Foundation, Inc., 51 Franklin Street,
19 // Boston, MA 02110-1301, USA.
21 #include <usrp/db_wbxng.h>
22 #include <usrp/db_wbxng_adf4350.h>
23 #include <db_base_impl.h>
25 // d'board i/o pin defs
26 // Tx and Rx have shared defs, but different i/o regs
27 #define ENABLE_5 (1 << 7) // enables 5.0V power supply
28 #define ENABLE_33 (1 << 6) // enables 3.3V supply
29 #define RX_TXN (1 << 5) // Tx only: T/R antenna switch for TX/RX port
30 #define RX2_RX1N (1 << 5) // Rx only: antenna switch between RX2 and TX/RX port
31 #define BBAMP_EN (1 << 4)
32 #define PLL_CE (1 << 3)
33 #define PLL_PDBRF (1 << 2)
34 #define PLL_MUXOUT (1 << 1)
35 #define PLL_LOCK_DETECT (1 << 0)
37 wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on)
38 : db_base(_usrp, which), d_power_on(_power_on)
41 @param usrp: instance of usrp.source_c
42 @param which: which side: 0 or 1 corresponding to side A or B respectively
47 d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0;
49 usrp()->_write_oe(d_which, 1, 0xffff); // turn off all outputs
50 _enable_refclk(false); // disable refclk
55 wbxng_base::~wbxng_base()
61 wbxng_base::_write_all(int R, int control, int N)
64 Write R counter latch, control latch and N counter latch to VCO.
66 Adds 10ms delay between writing control and N if this is first call.
67 This is the required power-up sequence.
69 @param R: 24-bit R counter latch
71 @param control: 24-bit control latch
73 @param N: 24-bit N counter latch
82 _write_control(control);
93 wbxng_base::_write_control(int control)
95 //_write_it((control & ~0x3) | 0);
99 wbxng_base::_write_R(int R)
101 //_write_it((R & ~0x3) | 1);
105 wbxng_base::_write_N(int N)
107 //_write_it((N & ~0x3) | 2);
111 wbxng_base::_write_it(int v)
114 s[0] = (char)((v >> 16) & 0xff);
115 s[1] = (char)((v >> 8) & 0xff);
116 s[2] = (char)(v & 0xff);
117 std::string str(s, 3);
118 //usrp()->_write_spi(0, d_spi_enable, d_spi_format, str);
122 wbxng_base::_lock_detect()
125 @returns: the value of the VCO/PLL lock detect bit.
129 if(d_common->_get_locked()){
132 else { // Give it a second chance
135 // FIXME: make portable sleep
138 t.tv_nsec = 100000000;
141 if(usrp()->read_io(d_which) & PLL_LOCK_DETECT) {
150 throw std::runtime_error("_lock_detect called from wbxng_base\n");
155 wbxng_base::_compute_regs(double freq, int &retR, int &retcontrol,
156 int &retN, double &retfreq)
159 Determine values of R, control, and N registers, along with actual freq.
161 @param freq: target frequency in Hz
163 @returns: (R, control, N, actual_freq)
164 @rtype: tuple(int, int, int, float)
166 Override this in derived classes.
169 //raise NotImplementedError;
170 throw std::runtime_error("_compute_regs called from wbxng_base\n");
175 wbxng_base::_compute_control_reg()
177 throw std::runtime_error("_compute_control_reg called from wbxng_base\n");
178 //return d_common->_compute_control_reg();
182 wbxng_base::_refclk_divisor()
184 throw std::runtime_error("_refclk_divisor called from wbxng_base\n");
185 //return d_common->_refclk_divisor();
189 wbxng_base::_refclk_freq()
191 throw std::runtime_error("_refclk_divisor called from wbxng_base\n");
192 // *** TODO *** Magic Number 64e6?
193 //return 64e6/_refclk_divisor();
197 wbxng_base::set_freq(double freq)
200 @returns (ok, actual_baseband_freq) where:
201 ok is True or False and indicates success or failure,
202 actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
205 freq_t int_freq = (freq_t) freq;
206 bool ok = d_common->_set_freq(int_freq);
207 double freq_result = (double) d_common->_get_freq();
208 struct freq_result_t args = {ok, freq_result};
210 // Offsetting the LO helps get the Tx carrier leakage out of the way.
211 // This also ensures that on Rx, we're not getting hosed by the
212 // FPGA's DC removal loop's time constant. We were seeing a
213 // problem when running with discontinuous transmission.
214 // Offsetting the LO made the problem go away.
215 //freq += d_lo_offset;
218 //double actual_freq;
219 //_compute_regs(freq, R, control, N, actual_freq);
225 //_write_all(R, control, N);
226 //args.ok = _lock_detect();
227 //args.baseband_freq = actual_freq;
232 wbxng_base::_set_pga(float pga_gain)
236 usrp()->set_pga(0, pga_gain);
237 usrp()->set_pga(1, pga_gain);
240 usrp()->set_pga(2, pga_gain);
241 usrp()->set_pga(3, pga_gain);
248 wbxng_base::is_quadrature()
251 Return True if this board requires both I & Q analog channels.
253 This bit of info is useful when setting up the USRP Rx mux register.
259 wbxng_base::freq_min()
261 return (double) d_common->_get_min_freq();
265 wbxng_base::freq_max()
267 return (double) d_common->_get_max_freq();
270 // ----------------------------------------------------------------
272 wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on)
273 : wbxng_base(_usrp, which, _power_on)
276 @param usrp: instance of usrp.sink_c
277 @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
281 d_spi_enable = SPI_ENABLE_TX_A;
284 d_spi_enable = SPI_ENABLE_TX_B;
287 d_common = new adf4350(_usrp, d_which, d_spi_enable);
289 // power up the transmit side, but don't enable the mixer
290 usrp()->_write_oe(d_which,(RX_TXN|ENABLE_33|ENABLE_5), 0xffff);
291 usrp()->write_io(d_which, (power_on()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5));
292 //set_lo_offset(4e6);
294 //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain
297 wbxng_base_tx::~wbxng_base_tx()
304 wbxng_base_tx::shutdown()
306 // fprintf(stderr, "wbxng_base_tx::shutdown d_is_shutdown = %d\n", d_is_shutdown);
309 d_is_shutdown = true;
310 // do whatever there is to do to shutdown
312 // Power down and leave the T/R switch in the R position
313 usrp()->write_io(d_which, (power_off()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5));
316 // Power down VCO/PLL
319 _write_control(_compute_control_reg());
321 _enable_refclk(false); // turn off refclk
327 wbxng_base_tx::set_auto_tr(bool on)
332 ok &= set_atr_mask (RX_TXN | ENABLE_33 | ENABLE_5);
333 ok &= set_atr_txval(0 | ENABLE_33 | ENABLE_5);
334 ok &= set_atr_rxval(RX_TXN | 0);
337 ok &= set_atr_mask (0);
338 ok &= set_atr_txval(0);
339 ok &= set_atr_rxval(0);
346 wbxng_base_tx::set_enable(bool on)
349 Enable transmitter if on is true
353 int mask = RX_TXN | ENABLE_5 | ENABLE_33;
355 v = ENABLE_5 | ENABLE_33;
360 return usrp()->write_io(d_which, v, mask);
364 wbxng_base_tx::gain_min()
366 return usrp()->pga_max();
370 wbxng_base_tx::gain_max()
372 return usrp()->pga_max();
376 wbxng_base_tx::gain_db_per_step()
382 wbxng_base_tx::set_gain(float gain)
387 @param gain: gain in decibels
390 return _set_pga(usrp()->pga_max());
394 /**************************************************************************/
397 wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on)
398 : wbxng_base(_usrp, which, _power_on)
401 @param usrp: instance of usrp.source_c
402 @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
406 d_spi_enable = SPI_ENABLE_RX_A;
409 d_spi_enable = SPI_ENABLE_RX_B;
412 d_common = new adf4350(_usrp, d_which, d_spi_enable);
414 usrp()->_write_oe(d_which, (RX2_RX1N|ENABLE_33|ENABLE_5), 0xffff);
415 usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE_33|ENABLE_5),
416 (RX2_RX1N|ENABLE_33|ENABLE_5));
418 // set up for RX on TX/RX port
419 select_rx_antenna("TX/RX");
421 bypass_adc_buffers(true);
428 wbxng_base_rx::~wbxng_base_rx()
434 wbxng_base_rx::shutdown()
436 // fprintf(stderr, "wbxng_base_rx::shutdown d_is_shutdown = %d\n", d_is_shutdown);
439 d_is_shutdown = true;
440 // do whatever there is to do to shutdown
443 usrp()->common_write_io(C_RX, d_which, power_off(), (ENABLE_33|ENABLE_5));
445 // Power down VCO/PLL
449 // fprintf(stderr, "wbxng_base_rx::shutdown before _write_control\n");
450 //_write_control(_compute_control_reg());
452 // fprintf(stderr, "wbxng_base_rx::shutdown before _enable_refclk\n");
453 _enable_refclk(false); // turn off refclk
455 // fprintf(stderr, "wbxng_base_rx::shutdown before set_auto_tr\n");
458 // fprintf(stderr, "wbxng_base_rx::shutdown after set_auto_tr\n");
463 wbxng_base_rx::set_auto_tr(bool on)
468 ok &= set_atr_mask (ENABLE_33|ENABLE_5);
469 ok &= set_atr_txval( 0);
470 ok &= set_atr_rxval(ENABLE_33|ENABLE_5);
473 ok &= set_atr_mask (0);
474 ok &= set_atr_txval(0);
475 ok &= set_atr_rxval(0);
482 wbxng_base_rx::select_rx_antenna(int which_antenna)
485 Specify which antenna port to use for reception.
486 @param which_antenna: either 'TX/RX' or 'RX2'
489 if(which_antenna == 0) {
490 usrp()->write_io(d_which, 0,RX2_RX1N);
492 else if(which_antenna == 1) {
493 usrp()->write_io(d_which, RX2_RX1N, RX2_RX1N);
497 // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
503 wbxng_base_rx::select_rx_antenna(const std::string &which_antenna)
506 Specify which antenna port to use for reception.
507 @param which_antenna: either 'TX/RX' or 'RX2'
511 if(which_antenna == "TX/RX") {
512 usrp()->write_io(d_which, 0, RX2_RX1N);
514 else if(which_antenna == "RX2") {
515 usrp()->write_io(d_which, RX2_RX1N, RX2_RX1N);
518 // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
526 wbxng_base_rx::set_gain(float gain)
531 @param gain: gain in decibels
537 gain = std::max(gain_min(), std::min(gain, gain_max()));
539 float pga_gain, agc_gain;
540 float V_maxgain, V_mingain, V_fullscale, dac_value;
542 float maxgain = gain_max() - usrp()->pga_max();
543 float mingain = gain_min();
545 pga_gain = gain-maxgain;
546 assert(pga_gain <= usrp()->pga_max());
557 dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale;
559 assert(dac_value>=0 && dac_value<4096);
561 return (usrp()->write_aux_dac(d_which, 0, int(dac_value))
562 && _set_pga(int(pga_gain)));
567 // ----------------------------------------------------------------
569 db_wbxng_tx::db_wbxng_tx(usrp_basic_sptr usrp, int which)
570 : wbxng_base_tx(usrp, which)
574 db_wbxng_tx::~db_wbxng_tx()
580 db_wbxng_tx::_compute_regs(double freq, int &retR, int &retcontrol,
581 int &retN, double &retfreq)
583 return d_common->_compute_regs(_refclk_freq(), freq, retR,
584 retcontrol, retN, retfreq);
589 db_wbxng_rx::db_wbxng_rx(usrp_basic_sptr usrp, int which)
590 : wbxng_base_rx(usrp, which)
592 set_gain((gain_min() + gain_max()) / 2.0); // initialize gain
595 db_wbxng_rx::~db_wbxng_rx()
600 db_wbxng_rx::gain_min()
602 return usrp()->pga_min();
606 db_wbxng_rx::gain_max()
608 return usrp()->pga_max()+70;
612 db_wbxng_rx::gain_db_per_step()
619 db_wbxng_rx::i_and_q_swapped()
626 db_wbxng_rx::_compute_regs(double freq, int &retR, int &retcontrol,
627 int &retN, double &retfreq)
629 return d_common->_compute_regs(_refclk_freq(), freq, retR,
630 retcontrol, retN, retfreq);