3 // Copyright 2008 Free Software Foundation, Inc.
5 // This file is part of GNU Radio
7 // GNU Radio is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either asversion 3, or (at your option)
12 // GNU Radio is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with GNU Radio; see the file COPYING. If not, write to
19 // the Free Software Foundation, Inc., 51 Franklin Street,
20 // Boston, MA 02110-1301, USA.
23 #include <fpga_regs_standard.h>
24 #include <fpga_regs_common.h>
25 #include <usrp_prims.h>
26 #include <usrp_spi_defs.h>
30 // d'board i/o pin defs
33 #define TX_POWER (1 << 0) // TX Side Power
34 #define RX_TXN (1 << 1) // T/R antenna switch for TX/RX port
35 #define TX_ENB_MIX (1 << 2) // Enable IQ mixer
36 #define TX_ENB_VGA (1 << 3)
39 #define RX2_RX1N (1 << 0) // antenna switch between RX2 and TX/RX port
40 #define RXENABLE (1 << 1) // enables mixer
41 #define PLL_LOCK_DETECT (1 << 2) // Muxout pin from PLL -- MUST BE INPUT
42 #define MReset (1 << 3) // NB6L239 Master Reset, asserted low
43 #define SELA0 (1 << 4) // NB6L239 SelA0
44 #define SELA1 (1 << 5) // NB6L239 SelA1
45 #define SELB0 (1 << 6) // NB6L239 SelB0
46 #define SELB1 (1 << 7) // NB6L239 SelB1
47 #define PLL_ENABLE (1 << 8) // CE Pin on PLL
48 #define AUX_SCLK (1 << 9) // ALT SPI SCLK
49 #define AUX_SDO (1 << 10) // ALT SPI SDO
50 #define AUX_SEN (1 << 11) // ALT SPI SEN
53 wbx_base::wbx_base(usrp_basic_sptr usrp, int which)
54 : db_base(usrp, which)
57 * @param usrp: instance of usrp.source_c
58 * @param which: which side: 0 or 1 corresponding to side A or B respectively
63 d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0;
65 // FIXME -- the write reg functions don't work with 0xffff for masks
66 _rx_write_oe(int(PLL_ENABLE|MReset|SELA0|SELA1|SELB0|SELB1|RX2_RX1N|RXENABLE), 0x7fff);
67 _rx_write_io((PLL_ENABLE|MReset|0|RXENABLE), (PLL_ENABLE|MReset|RX2_RX1N|RXENABLE));
69 _tx_write_oe((TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA), 0x7fff);
70 _tx_write_io((0|RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA)); // TX off, TR switch set to RX
73 d_spi_enable = SPI_ENABLE_RX_A;
76 d_spi_enable = SPI_ENABLE_RX_B;
94 // do whatever there is to do to shutdown
96 write_io(d_which, d_power_off, POWER_UP); // turn off power to board
97 _write_oe(d_which, 0, 0xffff); // turn off all outputs
98 set_auto_tr(false); // disable auto transmit
103 wbx_base::_lock_detect()
106 * @returns: the value of the VCO/PLL lock detect bit.
110 if(_rx_read_io() & PLL_LOCK_DETECT) {
113 else { // Give it a second chance
114 if(_rx_read_io() & PLL_LOCK_DETECT) {
124 wbx_base::_tx_write_oe(int value, int mask)
126 int reg = (d_which == 0 ? FR_OE_0 : FR_OE_2);
127 return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 0xffff));
131 wbx_base::_rx_write_oe(int value, int mask)
133 int reg = (d_which == 0 ? FR_OE_1 : FR_OE_3);
134 return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 0xffff));
138 wbx_base::_tx_write_io(int value, int mask)
140 int reg = (d_which == 0 ? FR_IO_0 : FR_IO_2);
141 return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 0xffff));
145 wbx_base::_rx_write_io(int value, int mask)
147 int reg = (d_which == 0 ? FR_IO_1 : FR_IO_3);
148 return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 0xffff));
152 wbx_base::_rx_read_io()
154 int reg = (d_which == 0 ? FR_RB_IO_RX_A_IO_TX_A : FR_RB_IO_RX_B_IO_TX_B);
155 int t = d_usrp->_read_fpga_reg(reg);
156 return (t >> 16) & 0xffff;
160 wbx_base::_tx_read_io()
162 int reg = (d_which == 0 ? FR_RB_IO_RX_A_IO_TX_A : FR_RB_IO_RX_B_IO_TX_B);
163 int t = d_usrp->_read_fpga_reg(reg);
168 wbx_base::_compute_regs(double freq)
171 * Determine values of registers, along with actual freq.
173 * @param freq: target frequency in Hz
175 * @returns: (R, N, func, init, actual_freq)
176 * @rtype: tuple(int, int, int, int, double)
178 * Override this in derived classes.
180 throw std::runtime_error("_compute_regs called from base class\n");
184 wbx_base::_refclk_freq()
186 return (double)(d_usrp->fpga_master_clock_freq())/_refclk_divisor();
190 wbx_base::_refclk_divisor()
193 * Return value to stick in REFCLK_DIVISOR register
199 wbx_base::set_freq(double freq)
202 * @returns (ok, actual_baseband_freq) where:
203 * ok is True or False and indicates success or failure,
204 * actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
206 throw std::runtime_error("set_freq called from base class\n");
212 throw std::runtime_error("gain_min called from base class\n");
218 throw std::runtime_error("gain_max called from base class\n");
222 wbx_base::gain_db_per_step()
224 throw std::runtime_error("gain_db_per_step called from base class\n");
228 wbx_base::set_gain(float gain)
233 * @param gain: gain in decibels
234 * @returns True/False
236 throw std::runtime_error("set_gain called from base class\n");
240 wbx_base::_set_pga(float pga_gain)
244 ok = d_usrp->set_pga(0, pga_gain);
245 ok |= d_usrp->set_pga(1, pga_gain);
248 ok = d_usrp->set_pga(2, pga_gain);
249 ok |= d_usrp->set_pga(3, pga_gain);
255 wbx_base::is_quadrature()
258 * Return True if this board requires both I & Q analog channels.
260 * This bit of info is useful when setting up the USRP Rx mux register.
266 /****************************************************************************/
269 wbx_base_tx::wbx_base_tx(usrp_basic_sptr usrp, int which)
270 : wbx_base(usrp, which)
273 * @param usrp: instance of usrp.sink_c
274 * @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
277 // power up the transmit side, NO -- but set antenna to receive
278 d_usrp->write_io(d_which, (TX_POWER), (TX_POWER|RX_TXN));
281 // Gain is not set by the PGA, but the PGA must be set at max gain in the TX
282 _set_pga(d_usrp->pga_max());
285 wbx_base_tx::~wbx_base_tx()
287 // Power down and leave the T/R switch in the R position
288 d_usrp->write_io(d_which, (RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA));
292 wbx_base_tx::set_auto_tr(bool on)
295 set_atr_mask (RX_TXN);
297 set_atr_rxval(RX_TXN);
307 wbx_base_tx::set_enable(bool on)
310 * Enable transmitter if on is True
313 int mask = RX_TXN|TX_ENB_MIX|TX_ENB_VGA;
314 //printf("HERE!!!!\n");
316 d_usrp->write_io(d_which, TX_ENB_MIX|TX_ENB_VGA, mask);
319 d_usrp->write_io(d_which, RX_TXN, mask);
324 wbx_base_tx::set_lo_offset(double offset)
327 * Set amount by which LO is offset from requested tuning frequency.
329 * @param offset: offset in Hz
332 d_lo_offset = offset;
336 wbx_base_tx::lo_offset()
339 * Get amount by which LO is offset from requested tuning frequency.
341 * @returns Offset in Hz
348 /****************************************************************************/
351 wbx_base_rx::wbx_base_rx(usrp_basic_sptr usrp, int which)
352 : wbx_base(usrp, which)
355 * @param usrp: instance of usrp.source_c
356 * @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
359 // set up for RX on TX/RX port
360 select_rx_antenna("TX/RX");
362 bypass_adc_buffers(true);
367 wbx_base_rx::~wbx_base_rx()
370 d_usrp->write_io(d_which, 0, (RXENABLE));
374 wbx_base_rx::set_auto_tr(bool on)
377 // FIXME: where does ENABLE come from?
378 //set_atr_mask (ENABLE);
380 //set_atr_rxval(ENABLE);
390 wbx_base_rx::select_rx_antenna(int which_antenna)
393 * Specify which antenna port to use for reception.
394 * @param which_antenna: either 'TX/RX' or 'RX2'
397 if(which_antenna == 0) {
398 d_usrp->write_io(d_which, 0, RX2_RX1N);
400 else if(which_antenna == 1) {
401 d_usrp->write_io(d_which, RX2_RX1N, RX2_RX1N);
404 throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
409 wbx_base_rx::select_rx_antenna(const std::string &which_antenna)
411 if(which_antenna == "TX/RX") {
412 select_rx_antenna(0);
414 else if(which_antenna == "RX2") {
415 select_rx_antenna(1);
418 throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
423 wbx_base_rx::set_gain(float gain)
428 * @param gain: gain in decibels
429 * @returns True/False
432 float pga_gain, agc_gain;
433 float maxgain = gain_max() - d_usrp->pga_max();
434 float mingain = gain_min();
436 pga_gain = gain-maxgain;
437 assert(pga_gain <= d_usrp->pga_max());
445 float V_maxgain = .2;
446 float V_mingain = 1.2;
447 float V_fullscale = 3.3;
448 float dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale;
450 assert(dac_value>=0 && dac_value<4096);
452 return d_usrp->write_aux_dac(d_which, 0, (int)(dac_value)) && _set_pga((int)(pga_gain));
456 wbx_base_rx::set_lo_offset(double offset)
459 * Set amount by which LO is offset from requested tuning frequency.
461 * @param offset: offset in Hz
463 d_lo_offset = offset;
467 wbx_base_rx::lo_offset()
470 * Get amount by which LO is offset from requested tuning frequency.
472 * @returns Offset in Hz
478 wbx_base_rx::i_and_q_swapped()
481 * Return True if this is a quadrature device and ADC 0 is Q.
487 /****************************************************************************/
489 _ADF410X_common::_ADF410X_common()
491 // R-Register Common Values
492 d_R_RSV = 0; // bits 23,22,21
493 d_LDP = 1; // bit 20 Lock detect in 5 cycles
494 d_TEST = 0; // bit 19,18 Normal
495 d_ABP = 0; // bit 17,16 2.9ns
497 // N-Register Common Values
498 d_N_RSV = 0; // 23,22
501 // Function Register Common Values
502 d_P = 0; // bits 23,22 0 = 8/9, 1 = 16/17, 2 = 32/33, 3 = 64/65
503 d_PD2 = 0; // bit 21 Normal operation
504 d_CP2 = 4; // bits 20,19,18 CP Gain = 5mA
505 d_CP1 = 4; // bits 17,16,15 CP Gain = 5mA
506 d_TC = 0; // bits 14-11 PFD Timeout
507 d_FL = 0; // bit 10,9 Fastlock Disabled
508 d_CP3S = 0; // bit 8 CP Enabled
509 d_PDP = 0; // bit 7 Phase detector polarity, Positive=1
510 d_MUXOUT = 1; // bits 6:4 Digital Lock Detect
511 d_PD1 = 0; // bit 3 Normal operation
512 d_CR = 0; // bit 2 Normal operation
515 _ADF410X_common::~_ADF410X_common()
520 _ADF410X_common::_compute_regs(double freq, int &retR, int &retcontrol,
521 int &retN, double &retfreq)
524 * Determine values of R, control, and N registers, along with actual freq.
526 * @param freq: target frequency in Hz
528 * @returns: (R, N, control, actual_freq)
529 * @rtype: tuple(int, int, int, double)
532 // Band-specific N-Register Values
533 double phdet_freq = _refclk_freq()/d_R_DIV;
534 printf("phdet_freq = %f\n", phdet_freq);
536 double desired_n = round(freq*d_freq_mult/phdet_freq);
537 printf("desired_n %f\n", desired_n);
539 double actual_freq = desired_n * phdet_freq;
540 printf("actual freq %f\n", actual_freq);
542 double B = floor(desired_n/_prescaler());
543 double A = desired_n - _prescaler()*B;
544 printf("A %f B %f\n", A, B);
546 d_B_DIV = int(B); // bits 20:8;
547 d_A_DIV = int(A); // bit 6:2;
549 if(d_B_DIV < d_A_DIV) {
557 retR = (d_R_RSV<<21) | (d_LDP<<20) | (d_TEST<<18) |
558 (d_ABP<<16) | (d_R_DIV<<2);
560 retN = (d_N_RSV<<22) | (d_CP_GAIN<<21) | (d_B_DIV<<8) | (d_A_DIV<<2);
562 retcontrol = (d_P<<22) | (d_PD2<<21) | (d_CP2<<18) | (d_CP1<<15) |
563 (d_TC<<11) | (d_FL<<9) | (d_CP3S<<8) | (d_PDP<<7) |
564 (d_MUXOUT<<4) | (d_PD1<<3) | (d_CR<<2);
566 retfreq = actual_freq/d_freq_mult;
572 _ADF410X_common::_write_all(int R, int N, int control)
575 * Write all PLL registers:
579 * Initialization latch
581 * Adds 10ms delay between writing control and N if this is first call.
582 * This is the required power-up sequence.
584 * @param R: 24-bit R counter latch
586 * @param N: 24-bit N counter latch
588 * @param control: 24-bit control latch
591 static bool first = true;
595 t.tv_nsec = 10000000;
598 _write_func(control);
599 _write_init(control);
609 _ADF410X_common::_write_R(int R)
611 _write_it((R & ~0x3) | 0);
615 _ADF410X_common::_write_N(int N)
617 _write_it((N & ~0x3) | 1);
621 _ADF410X_common::_write_func(int func)
623 _write_it((func & ~0x3) | 2);
627 _ADF410X_common::_write_init(int init)
629 _write_it((init & ~0x3) | 3);
633 _ADF410X_common::_write_it(int v)
636 c[0] = (char)((v >> 16) & 0xff);
637 c[1] = (char)((v >> 8) & 0xff);
638 c[2] = (char)((v & 0xff));
640 //d_usrp->_write_spi(0, d_spi_enable, d_spi_format, s);
641 usrp()->_write_spi(0, d_spi_enable, d_spi_format, s);
645 _ADF410X_common::_prescaler()
660 throw std::invalid_argument("Prescaler out of range\n");
665 _ADF410X_common::_refclk_freq()
667 throw std::runtime_error("_refclk_freq called from base class.");
671 _ADF410X_common::_rx_write_io(int value, int mask)
673 throw std::runtime_error("_rx_write_io called from base class.");
677 _ADF410X_common::_lock_detect()
679 throw std::runtime_error("_lock_detect called from base class.");
683 _ADF410X_common::usrp()
685 throw std::runtime_error("usrp() called from base class.");
689 /****************************************************************************/
692 _lo_common::_lo_common()
695 // Band-specific R-Register Values
696 d_R_DIV = 4; // bits 15:2
698 // Band-specific C-Register values
699 d_P = 0; // bits 23,22 0 = Div by 8/9
700 d_CP2 = 4; // bits 19:17
701 d_CP1 = 4; // bits 16:14
703 // Band specifc N-Register Values
704 d_DIVSEL = 0; // bit 23
705 d_DIV2 = 0; // bit 22
706 d_CPGAIN = 0; // bit 21
714 _lo_common::~_lo_common()
719 _lo_common::freq_min()
725 _lo_common::freq_max()
731 _lo_common::set_divider(int main_or_aux, int divisor)
733 if(main_or_aux == 0) {
734 if((divisor != 1) || (divisor != 2) || (divisor != 4) || (divisor != 8)) {
735 throw std::invalid_argument("Main Divider Must be 1, 2, 4, or 8\n");
737 d_main_div = (int)(log10(divisor)/log10(2.0));
739 else if(main_or_aux == 1) {
740 if((divisor != 2) || (divisor != 4) || (divisor != 8) || (divisor != 16)) {
741 throw std::invalid_argument("Aux Divider Must be 2, 4, 8 or 16\n");
743 d_main_div = (int)(log10(divisor/2.0)/log10(2.0));
746 throw std::invalid_argument("main_or_aux must be 'main' or 'aux'\n");
749 int vala = d_main_div*SELA0;
750 int valb = d_aux_div*SELB0;
751 int mask = SELA0|SELA1|SELB0|SELB1;
753 _rx_write_io((vala | valb), mask);
757 _lo_common::set_divider(const std::string &main_or_aux, int divisor)
759 if(main_or_aux == "main") {
760 set_divider(0, divisor);
762 else if(main_or_aux == "aux") {
763 set_divider(1, divisor);
766 throw std::invalid_argument("main_or_aux must be 'main' or 'aux'\n");
771 _lo_common::set_freq(double freq)
773 struct freq_result_t ret;
775 if(freq < 20e6 or freq > 1200e6) {
776 throw std::invalid_argument("Requested frequency out of range\n");
780 double lo_freq = freq * 2;
781 while((lo_freq < 1e9) && (div < 8)) {
783 lo_freq = lo_freq * 2;
786 printf("For RF freq of %f, we set DIV=%d and LO Freq=%f\n", freq, div, lo_freq);
788 set_divider("main", div);
789 set_divider("aux", div*2);
793 _compute_regs(lo_freq, R, N, control, actual_freq);
795 printf("R %d N %d control %d actual freq %f\n", R, N, control, actual_freq);
798 ret.baseband_freq = 0.0;
801 _write_all(R, N, control);
803 ret.ok = _lock_detect();
804 ret.baseband_freq = actual_freq/div/2;
809 /****************************************************************************/
812 db_wbx_lo_tx::db_wbx_lo_tx(usrp_basic_sptr usrp, int which)
814 wbx_base_tx(usrp, which)
818 db_wbx_lo_tx::~db_wbx_lo_tx()
823 db_wbx_lo_tx::gain_min()
829 db_wbx_lo_tx::gain_max()
835 db_wbx_lo_tx::gain_db_per_step()
841 db_wbx_lo_tx::set_gain(float gain)
846 * @param gain: gain in decibels
847 * @returns True/False
851 float maxgain = gain_max();
852 float mingain = gain_min();
854 txvga_gain = maxgain;
856 else if(gain < mingain) {
857 txvga_gain = mingain;
863 float V_maxgain = 1.4;
864 float V_mingain = 0.1;
865 float V_fullscale = 3.3;
866 float dac_value = ((txvga_gain-mingain)*(V_maxgain-V_mingain)/
867 (maxgain-mingain) + V_mingain)*4096/V_fullscale;
869 assert(dac_value>=0 && dac_value<4096);
870 printf("DAC value %f\n", dac_value);
872 return d_usrp->write_aux_dac(d_which, 1, (int)(dac_value));
876 db_wbx_lo_tx::_refclk_freq()
878 return wbx_base::_refclk_freq();
882 db_wbx_lo_tx::_rx_write_io(int value, int mask)
884 return wbx_base::_rx_write_io(value, mask);
888 db_wbx_lo_tx::_lock_detect()
890 return wbx_base::_lock_detect();
900 /****************************************************************************/
903 db_wbx_lo_rx::db_wbx_lo_rx(usrp_basic_sptr usrp, int which)
905 wbx_base_rx(usrp, which)
909 db_wbx_lo_rx::~db_wbx_lo_rx()
914 db_wbx_lo_rx::gain_min()
916 return d_usrp->pga_min();
920 db_wbx_lo_rx::gain_max()
922 return d_usrp->pga_max() + 45;
926 db_wbx_lo_rx::gain_db_per_step()
932 db_wbx_lo_rx::_refclk_freq()
934 return wbx_base::_refclk_freq();
938 db_wbx_lo_rx::_rx_write_io(int value, int mask)
940 return wbx_base::_rx_write_io(value, mask);
944 db_wbx_lo_rx::_lock_detect()
946 return wbx_base::_lock_detect();