summaryrefslogtreecommitdiff
path: root/usrp/host/lib/db_wbxng.cc
diff options
context:
space:
mode:
Diffstat (limited to 'usrp/host/lib/db_wbxng.cc')
-rw-r--r--usrp/host/lib/db_wbxng.cc1061
1 files changed, 442 insertions, 619 deletions
diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc
index 53ec27afc..e911c9d03 100644
--- a/usrp/host/lib/db_wbxng.cc
+++ b/usrp/host/lib/db_wbxng.cc
@@ -1,5 +1,5 @@
//
-// Copyright 2008,2009 Free Software Foundation, Inc.
+// Copyright 2008 Free Software Foundation, Inc.
//
// This file is part of GNU Radio
//
@@ -19,791 +19,614 @@
// Boston, MA 02110-1301, USA.
#include <usrp/db_wbxng.h>
+#include <usrp/db_wbxng_adf4350.h>
#include <db_base_impl.h>
-#include <cmath>
-#include <boost/thread.hpp>
-#include <boost/weak_ptr.hpp>
-#include <cstdio>
-
-#if 0
-#define LO_OFFSET 4.25e6
-#else
-#define LO_OFFSET 0
-#define NO_LO_OFFSET
-#endif
-
-
-/* ------------------------------------------------------------------------
- * **** TODO ****
- * Fix the comment below to reflect WBX NG
- */
-
-/* ------------------------------------------------------------------------
- * A few comments about the XCVR2450:
- *
- * It is half-duplex. I.e., transmit and receive are mutually exclusive.
- * There is a single LO for both the Tx and Rx sides.
- * For our purposes the board is always either receiving or transmitting.
- *
- * Each board is uniquely identified by the *USRP hardware* instance and side
- * This dictionary holds a weak reference to existing board controller so it
- * can be created or retrieved as needed.
- */
-
-
-
-// TX IO Pins
-#define HB_PA_OFF (1 << 15) // 5GHz PA, 1 = off, 0 = on
-#define LB_PA_OFF (1 << 14) // 2.4GHz PA, 1 = off, 0 = on
-#define ANTSEL_TX1_RX2 (1 << 13) // 1 = Ant 1 to TX, Ant 2 to RX
-#define ANTSEL_TX2_RX1 (1 << 12) // 1 = Ant 2 to TX, Ant 1 to RX
-#define TX_EN (1 << 11) // 1 = TX on, 0 = TX off
-#define AD9515DIV (1 << 4) // 1 = Div by 3, 0 = Div by 2
-
-#define TX_OE_MASK HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2|ANTSEL_TX2_RX1|TX_EN|AD9515DIV
-#define TX_SAFE_IO HB_PA_OFF|LB_PA_OFF|ANTSEL_TX1_RX2|AD9515DIV
-
-// RX IO Pins
-#define LOCKDET (1 << 15) // This is an INPUT!!!
-#define EN (1 << 14)
-#define RX_EN (1 << 13) // 1 = RX on, 0 = RX off
-#define RX_HP (1 << 12)
-#define RX_OE_MASK EN|RX_EN|RX_HP
-#define RX_SAFE_IO EN
-
-struct wbxng_key {
- std::string serial_no;
- int which;
-
- bool operator==(const wbxng_key &x){
- return x.serial_no ==serial_no && x.which == which;
- }
-};
-
-class wbxng
-{
-private:
- usrp_basic *d_raw_usrp;
- int d_which;
-
- bool d_is_shutdown;
- int d_spi_format, d_spi_enable;
-
- int d_mimo, d_int_div, d_frac_div, d_highband, d_five_gig;
- int d_cp_current, d_ref_div, d_rssi_hbw;
- int d_txlpf_bw, d_rxlpf_bw, d_rxlpf_fine, d_rxvga_ser;
- int d_rssi_range, d_rssi_mode, d_rssi_mux;
- int d_rx_hp_pin, d_rx_hpf, d_rx_ant;
- int d_tx_ant, d_txvga_ser, d_tx_driver_lin;
- int d_tx_vga_lin, d_tx_upconv_lin, d_tx_bb_gain;
- int d_pabias_delay, d_pabias, rx_rf_gain, rx_bb_gain, d_txgain;
- int d_rx_rf_gain, d_rx_bb_gain;
-
- int d_reg_standby, d_reg_int_divider, d_reg_frac_divider, d_reg_bandselpll;
- int d_reg_cal, dsend_reg, d_reg_lpf, d_reg_rxrssi_ctrl, d_reg_txlin_gain;
- int d_reg_pabias, d_reg_rxgain, d_reg_txgain;
-
- int d_ad9515_div;
-
- void _set_rfagc(float gain);
- void _set_ifagc(float gain);
- void _set_pga(float pga_gain);
-
-public:
- usrp_basic *usrp(){
- return d_raw_usrp;
- }
-
- wbxng(usrp_basic_sptr usrp, int which);
- ~wbxng();
- void shutdown();
-
- void set_reg_standby();
-
- // Integer-Divider Ratio (3)
- void set_reg_int_divider();
-
- // Fractional-Divider Ratio (4)
- void set_reg_frac_divider();
-
- // Band Select and PLL (5)
- void set_reg_bandselpll();
-
- // Calibration (6)
- void set_reg_cal();
-
- // Lowpass Filter (7)
- void set_reg_lpf();
-
- // Rx Control/RSSI (8)
- void set_reg_rxrssi_ctrl();
-
- // Tx Linearity/Baseband Gain (9)
- void set_reg_txlin_gain();
-
- // PA Bias DAC (10)
- void set_reg_pabias();
-
- // Rx Gain (11)
- void set_reg_rxgain();
-
- // Tx Gain (12)
- void set_reg_txgain();
-
- // Send register write to SPI
- void send_reg(int v);
-
- void set_gpio();
- bool lock_detect();
- bool set_rx_gain(float gain);
- bool set_tx_gain(float gain);
-
- struct freq_result_t set_freq(double target_freq);
-};
-
-
-/*****************************************************************************/
-
-wbxng::wbxng(usrp_basic_sptr _usrp, int which)
- : d_raw_usrp(_usrp.get()), d_which(which), d_is_shutdown(false)
+// d'board i/o pin defs
+// Tx and Rx have shared defs, but different i/o regs
+#define ENABLE_5 (1 << 7) // enables 5.0V power supply
+#define ENABLE_33 (1 << 6) // enables 3.3V supply
+#define RX_TXN (1 << 5) // Tx only: T/R antenna switch for TX/RX port
+#define RX2_RX1N (1 << 5) // Rx only: antenna switch between RX2 and TX/RX port
+#define BBAMP_EN (1 << 4)
+#define PLL_CE (1 << 3)
+#define PLL_PDBRF (1 << 2)
+#define PLL_MUXOUT (1 << 1)
+#define PLL_LOCK_DETECT (1 << 0)
+
+wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on)
+ : db_base(_usrp, which), d_power_on(_power_on)
{
- // Handler for WBX NG daughterboards.
- //
- // @param usrp: instance of usrp.source_c
- // @param which: which side: 0, 1 corresponding to RX_A or RX_B respectively
+ /*
+ @param usrp: instance of usrp.source_c
+ @param which: which side: 0 or 1 corresponding to side A or B respectively
+ @type which: int
+ */
- // Use MSB with no header
+ d_first = true;
d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0;
- if(which == 0) {
- d_spi_enable = SPI_ENABLE_RX_A;
- }
- else {
- d_spi_enable = SPI_ENABLE_RX_B;
- }
-
- // Sane defaults
- d_mimo = 1; // 0 = OFF, 1 = ON
- d_int_div = 192; // 128 = min, 255 = max
- d_frac_div = 0; // 0 = min, 65535 = max
- d_highband = 0; // 0 = freq <= 5.4e9, 1 = freq > 5.4e9
- d_five_gig = 0; // 0 = freq <= 3.e9, 1 = freq > 3e9
- d_cp_current = 1; // 0 = 2mA, 1 = 4mA
- d_ref_div = 1; // 1 to 7
- d_rssi_hbw = 0; // 0 = 2 MHz, 1 = 6 MHz
- d_txlpf_bw = 1; // 1 = 12 MHz, 2 = 18 MHz, 3 = 24 MHz
- d_rxlpf_bw = 1; // 0 = 7.5 MHz, 1 = 9.5 MHz, 2 = 14 MHz, 3 = 18 MHz
- d_rxlpf_fine = 2; // 0 = 90%, 1 = 95%, 2 = 100%, 3 = 105%, 4 = 110%
- d_rxvga_ser = 1; // 0 = RXVGA controlled by B7:1, 1=controlled serially
- d_rssi_range = 1; // 0 = low range (datasheet typo), 1=high range (0.5V - 2.0V)
- d_rssi_mode = 1; // 0 = enable follows RXHP, 1 = enabled
- d_rssi_mux = 0; // 0 = RSSI, 1 = TEMP
- d_rx_hp_pin = 0; // 0 = Fc set by rx_hpf, 1 = 600 KHz
- d_rx_hpf = 0; // 0 = 100Hz, 1 = 30KHz
- d_rx_ant = 0; // 0 = Ant. #1, 1 = Ant. #2
- d_tx_ant = 0; // 0 = Ant. #1, 1 = Ant. #2
- d_txvga_ser = 1; // 0 = TXVGA controlled by B6:1, 1=controlled serially
- d_tx_driver_lin = 2; // 0=50% (worst linearity), 1=63%, 2=78%, 3=100% (best lin)
- d_tx_vga_lin = 2; // 0=50% (worst linearity), 1=63%, 2=78%, 3=100% (best lin)
- d_tx_upconv_lin = 2; // 0=50% (worst linearity), 1=63%, 2=78%, 3=100% (best lin)
- d_tx_bb_gain = 3; // 0=maxgain-5dB, 1=max-3dB, 2=max-1.5dB, 3=max
- d_pabias_delay = 15; // 0 = 0, 15 = 7uS
- d_pabias = 0; // 0 = 0 uA, 63 = 315uA
- d_rx_rf_gain = 0; // 0 = 0dB, 1 = 0dB, 2 = 15dB, 3 = 30dB
- d_rx_bb_gain = 16; // 0 = min, 31 = max (0 - 62 dB)
-
- d_txgain = 63; // 0 = min, 63 = max
+ usrp()->_write_oe(d_which, 0, 0xffff); // turn off all outputs
+ _enable_refclk(false); // disable refclk
- /*
- // Initialize GPIO and ATR
- usrp()->common_write_io(C_TX, d_which, TX_SAFE_IO, TX_OE_MASK);
- usrp()->_common_write_oe(C_TX, d_which, TX_OE_MASK, 0xffff);
- usrp()->common_write_atr_txval(C_TX, d_which, TX_SAFE_IO);
- usrp()->common_write_atr_rxval(C_TX, d_which, TX_SAFE_IO);
- usrp()->common_write_atr_mask(C_TX, d_which, TX_OE_MASK);
-
- usrp()->common_write_io(C_RX, d_which, RX_SAFE_IO, RX_OE_MASK);
- usrp()->_common_write_oe(C_RX, d_which, RX_OE_MASK, 0xffff);
- usrp()->common_write_atr_txval(C_RX, d_which, RX_SAFE_IO);
- usrp()->common_write_atr_rxval(C_RX, d_which, RX_SAFE_IO);
- usrp()->common_write_atr_mask(C_RX, d_which, RX_OE_MASK);
-
- // Initialize chipset
- // TODO: perform reset sequence to ensure power up defaults
- set_reg_standby();
- set_reg_bandselpll();
- set_reg_cal();
- set_reg_lpf();
- set_reg_rxrssi_ctrl();
- set_reg_txlin_gain();
- set_reg_pabias();
- set_reg_rxgain();
- set_reg_txgain();
- //FIXME: set_freq(2.45e9);
- */
+ set_auto_tr(false);
}
-wbxng::~wbxng()
+wbxng_base::~wbxng_base()
{
- //printf("wbxng::destructor\n");
- shutdown();
+ delete d_common;
}
void
-wbxng::shutdown()
+wbxng_base::_write_all(int R, int control, int N)
{
- if (!d_is_shutdown){
- d_is_shutdown = true;
- /*
- usrp()->common_write_atr_txval(C_TX, d_which, TX_SAFE_IO);
- usrp()->common_write_atr_rxval(C_TX, d_which, TX_SAFE_IO);
- usrp()->common_write_atr_txval(C_RX, d_which, RX_SAFE_IO);
- usrp()->common_write_atr_rxval(C_RX, d_which, RX_SAFE_IO);
- */
+ /*
+ Write R counter latch, control latch and N counter latch to VCO.
+
+ Adds 10ms delay between writing control and N if this is first call.
+ This is the required power-up sequence.
+
+ @param R: 24-bit R counter latch
+ @type R: int
+ @param control: 24-bit control latch
+ @type control: int
+ @param N: 24-bit N counter latch
+ @type N: int
+ */
+ timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 10000000;
+
+ /*
+ _write_R(R);
+ _write_control(control);
+ if(d_first) {
+ //time.sleep(0.010);
+ nanosleep(&t, NULL);
+ d_first = false;
}
+ _write_N(N);
+ */
}
-
void
-wbxng::set_reg_standby()
+wbxng_base::_write_control(int control)
{
- d_reg_standby = ((d_mimo<<17) |
- (1<<16) |
- (1<<6) |
- (1<<5) |
- (1<<4) | 2);
- //send_reg(d_reg_standby);
+ //_write_it((control & ~0x3) | 0);
}
void
-wbxng::set_reg_int_divider()
+wbxng_base::_write_R(int R)
{
- d_reg_int_divider = (((d_frac_div & 0x03)<<16) |
- (d_int_div<<4) | 3);
- //send_reg(d_reg_int_divider);
+ //_write_it((R & ~0x3) | 1);
}
void
-wbxng::set_reg_frac_divider()
-{
- d_reg_frac_divider = ((d_frac_div & 0xfffc)<<2) | 4;
- //send_reg(d_reg_frac_divider);
-}
-
-void
-wbxng::set_reg_bandselpll()
-{
- d_reg_bandselpll = ((d_mimo<<17) |
- (1<<16) |
- (1<<15) |
- (0<<11) |
- (d_highband<<10) |
- (d_cp_current<<9) |
- (d_ref_div<<5) |
- (d_five_gig<<4) | 5);
- //send_reg(d_reg_bandselpll);
- d_reg_bandselpll = ((d_mimo<<17) |
- (1<<16) |
- (1<<15) |
- (1<<11) |
- (d_highband<<10) |
- (d_cp_current<<9) |
- (d_ref_div<<5) |
- (d_five_gig<<4) | 5);
- //send_reg(d_reg_bandselpll);
-}
-
-void
-wbxng::set_reg_cal()
+wbxng_base::_write_N(int N)
{
- // FIXME do calibration
- d_reg_cal = (1<<14)|6;
- //send_reg(d_reg_cal);
+ //_write_it((N & ~0x3) | 2);
}
void
-wbxng::set_reg_lpf()
+wbxng_base::_write_it(int v)
{
- d_reg_lpf = (
- (d_rssi_hbw<<15) |
- (d_txlpf_bw<<10) |
- (d_rxlpf_bw<<9) |
- (d_rxlpf_fine<<4) | 7);
- //send_reg(d_reg_lpf);
+ char s[3];
+ s[0] = (char)((v >> 16) & 0xff);
+ s[1] = (char)((v >> 8) & 0xff);
+ s[2] = (char)(v & 0xff);
+ std::string str(s, 3);
+ //usrp()->_write_spi(0, d_spi_enable, d_spi_format, str);
}
-
-void
-wbxng::set_reg_rxrssi_ctrl()
+
+bool
+wbxng_base::_lock_detect()
{
- d_reg_rxrssi_ctrl = ((d_rxvga_ser<<16) |
- (d_rssi_range<<15) |
- (d_rssi_mode<<14) |
- (d_rssi_mux<<12) |
- (1<<9) |
- (d_rx_hpf<<6) |
- (1<<4) | 8);
- //send_reg(d_reg_rxrssi_ctrl);
+ /*
+ @returns: the value of the VCO/PLL lock detect bit.
+ @rtype: 0 or 1
+ */
+ /*
+ if(usrp()->read_io(d_which) & PLL_LOCK_DETECT) {
+ return true;
+ }
+ else { // Give it a second chance
+ // FIXME: make portable sleep
+ timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 100000000;
+ nanosleep(&t, NULL);
+
+ if(usrp()->read_io(d_which) & PLL_LOCK_DETECT) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ */
+ throw std::runtime_error("_lock_detect called from wbxng_base\n");
}
-void
-wbxng::set_reg_txlin_gain()
-{
- d_reg_txlin_gain = ((d_txvga_ser<<14) |
- (d_tx_driver_lin<<12) |
- (d_tx_vga_lin<<10) |
- (d_tx_upconv_lin<<6) |
- (d_tx_bb_gain<<4) | 9);
- //send_reg(d_reg_txlin_gain);
+/*
+bool
+wbxng_base::_compute_regs(double freq, int &retR, int &retcontrol,
+ int &retN, double &retfreq)
+{
+ **COMMENT**
+ Determine values of R, control, and N registers, along with actual freq.
+
+ @param freq: target frequency in Hz
+ @type freq: float
+ @returns: (R, control, N, actual_freq)
+ @rtype: tuple(int, int, int, float)
+
+ Override this in derived classes.
+ **COMMENT**
+
+ //raise NotImplementedError;
+ throw std::runtime_error("_compute_regs called from wbxng_base\n");
}
+*/
-void
-wbxng::set_reg_pabias()
+int
+wbxng_base::_compute_control_reg()
{
- d_reg_pabias = (
- (d_pabias_delay<<10) |
- (d_pabias<<4) | 10);
- //send_reg(d_reg_pabias);
+ throw std::runtime_error("_compute_control_reg called from wbxng_base\n");
+ //return d_common->_compute_control_reg();
}
-void
-wbxng::set_reg_rxgain()
+int
+wbxng_base::_refclk_divisor()
{
- d_reg_rxgain = (
- (d_rx_rf_gain<<9) |
- (d_rx_bb_gain<<4) | 11);
- //send_reg(d_reg_rxgain);
+ throw std::runtime_error("_refclk_divisor called from wbxng_base\n");
+ //return d_common->_refclk_divisor();
}
-void
-wbxng::set_reg_txgain()
+double
+wbxng_base::_refclk_freq()
{
- d_reg_txgain = (d_txgain<<4) | 12;
- //send_reg(d_reg_txgain);
-}
-
-void
-wbxng::send_reg(int v)
-{
- // Send 24 bits, it keeps last 18 clocked in
- char c[3];
- c[0] = (char)((v >> 16) & 0xff);
- c[1] = (char)((v >> 8) & 0xff);
- c[2] = (char)((v & 0xff));
- std::string s(c, 3);
-
- //usrp()->_write_spi(0, d_spi_enable, d_spi_format, s);
- //printf("wbxng: Setting reg %d to %X\n", (v&15), v);
+ throw std::runtime_error("_refclk_divisor called from wbxng_base\n");
+ // *** TODO *** Magic Number 64e6?
+ //return 64e6/_refclk_divisor();
}
-// ----------------------------------------------------------------
-
-void
-wbxng::set_gpio()
-{
- // We calculate four values:
- //
- // io_rx_while_rx: what to drive onto io_rx_* when receiving
- // io_rx_while_tx: what to drive onto io_rx_* when transmitting
- // io_tx_while_rx: what to drive onto io_tx_* when receiving
- // io_tx_while_tx: what to drive onto io_tx_* when transmitting
- //
- // B1-B7 is ignored as gain is set serially for now.
-
- int rx_hp, tx_antsel, rx_antsel, tx_pa_sel;
- if(d_rx_hp_pin)
- rx_hp = RX_HP;
- else
- rx_hp = 0;
-
- if(d_tx_ant)
- tx_antsel = ANTSEL_TX2_RX1;
- else
- tx_antsel = ANTSEL_TX1_RX2;
-
- if(d_rx_ant)
- rx_antsel = ANTSEL_TX2_RX1;
- else
- rx_antsel = ANTSEL_TX1_RX2;
-
- if(d_five_gig)
- tx_pa_sel = LB_PA_OFF;
- else
- tx_pa_sel = HB_PA_OFF;
-
+struct freq_result_t
+wbxng_base::set_freq(double freq)
+{
/*
- // Reset GPIO and ATR
- // FIXME: dont set io, oe, atr mask once basic code stops overriding our settings
- usrp()->common_write_io(C_TX, d_which, TX_SAFE_IO, TX_OE_MASK);
- usrp()->_common_write_oe(C_TX, d_which, TX_OE_MASK, 0xffff);
- usrp()->common_write_atr_txval(C_TX, d_which, tx_pa_sel|tx_antsel|TX_EN|AD9515DIV);
- usrp()->common_write_atr_rxval(C_TX, d_which, HB_PA_OFF|LB_PA_OFF|rx_antsel|AD9515DIV);
- usrp()->common_write_atr_mask(C_TX, d_which, TX_OE_MASK);
-
- usrp()->common_write_io(C_RX, d_which, RX_SAFE_IO, RX_OE_MASK);
- usrp()->_common_write_oe(C_RX, d_which, RX_OE_MASK, 0xffff);
- usrp()->common_write_atr_txval(C_RX, d_which, EN|rx_hp);
- usrp()->common_write_atr_rxval(C_RX, d_which, EN|rx_hp|RX_EN);
- usrp()->common_write_atr_mask(C_RX, d_which, RX_OE_MASK);
+ @returns (ok, actual_baseband_freq) where:
+ ok is True or False and indicates success or failure,
+ actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
*/
- //printf("GPIO: RXRX=%04X RXTX=%04X TXRX=%04X TXTX=%04X\n",
- // io_rx_while_rx, io_rx_while_tx, io_tx_while_rx, io_tx_while_tx);
-}
-
-
-struct freq_result_t
-wbxng::set_freq(double target_freq)
-{
struct freq_result_t args = {false, 0};
- double scaler;
-
- if(target_freq > 3e9) {
- d_five_gig = 1;
- d_ad9515_div = 3;
- scaler = 4.0/5.0;
- }
- else {
- d_five_gig = 0;
- d_ad9515_div = 3;
- scaler = 4.0/3.0;
- }
-
- if(target_freq > 5.408e9) {
- d_highband = 1;
- }
- else {
- d_highband = 0;
- }
-
- double vco_freq = target_freq*scaler;
- double sys_clk = usrp()->fpga_master_clock_freq(); // Usually 64e6
- double ref_clk = sys_clk / d_ad9515_div;
-
- double phdet_freq = ref_clk/d_ref_div;
- double div = vco_freq/phdet_freq;
- d_int_div = int(floor(div));
- d_frac_div = int((div-d_int_div)*65536.0);
- // double actual_freq = phdet_freq*(d_int_div+(d_frac_div/65536.0))/scaler;
+ // Offsetting the LO helps get the Tx carrier leakage out of the way.
+ // This also ensures that on Rx, we're not getting hosed by the
+ // FPGA's DC removal loop's time constant. We were seeing a
+ // problem when running with discontinuous transmission.
+ // Offsetting the LO made the problem go away.
+ freq += d_lo_offset;
- //printf("RF=%f VCO=%f R=%d PHD=%f DIV=%3.5f I=%3d F=%5d ACT=%f\n",
- // target_freq, vco_freq, d_ref_div, phdet_freq,
- // div, d_int_div, d_frac_div, actual_freq);
-
- args.ok = lock_detect();
-
- /*
- set_gpio();
- set_reg_int_divider();
- set_reg_frac_divider();
- set_reg_bandselpll();
-
- args.ok = lock_detect();
-#ifdef NO_LO_OFFSET
- args.baseband_freq = target_freq;
-#else
- args.baseband_freq = actual_freq;
-#endif
- */
-
- if(!args.ok){
- printf("Fail %f\n", target_freq);
- }
+ //int R, control, N;
+ //double actual_freq;
+ //_compute_regs(freq, R, control, N, actual_freq);
+
+ //if(R==0) {
+ // return args;
+ //}
+
+ //_write_all(R, control, N);
+ //args.ok = _lock_detect();
+ //args.baseband_freq = actual_freq;
return args;
}
bool
-wbxng::lock_detect()
+wbxng_base::_set_pga(float pga_gain)
{
/*
- @returns: the value of the VCO/PLL lock detect bit.
- @rtype: 0 or 1
- */
- /*
- if(usrp()->common_read_io(C_RX, d_which) & LOCKDET) {
- return true;
+ if(d_which == 0) {
+ usrp()->set_pga(0, pga_gain);
+ usrp()->set_pga(1, pga_gain);
}
- else { // Give it a second chance
- if(usrp()->common_read_io(C_RX, d_which) & LOCKDET)
- return true;
- else
- return false;
+ else {
+ usrp()->set_pga(2, pga_gain);
+ usrp()->set_pga(3, pga_gain);
}
*/
return true;
}
bool
-wbxng::set_rx_gain(float gain)
-{
- if(gain < 0.0)
- gain = 0.0;
- if(gain > 92.0)
- gain = 92.0;
-
- // Split the gain between RF and baseband
- // This is experimental, not prescribed
- if(gain < 31.0) {
- d_rx_rf_gain = 0; // 0 dB RF gain
- rx_bb_gain = int(gain/2.0);
- }
-
- if(gain >= 30.0 and gain < 60.5) {
- d_rx_rf_gain = 2; // 15 dB RF gain
- d_rx_bb_gain = int((gain-15.0)/2.0);
- }
-
- if(gain >= 60.5) {
- d_rx_rf_gain = 3; // 30.5 dB RF gain
- d_rx_bb_gain = int((gain-30.5)/2.0);
- }
-
- //set_reg_rxgain();
-
+wbxng_base::is_quadrature()
+{
+ /*
+ Return True if this board requires both I & Q analog channels.
+
+ This bit of info is useful when setting up the USRP Rx mux register.
+ */
return true;
}
-bool
-wbxng::set_tx_gain(float gain)
+double
+wbxng_base::freq_min()
{
- if(gain < 0.0) {
- gain = 0.0;
- }
- if(gain > 30.0) {
- gain = 30.0;
- }
-
- d_txgain = int((gain/30.0)*63);
- //set_reg_txgain();
-
- return true;
+ throw std::runtime_error("freq_min called from wbxng_base\n");
+ //return d_common->freq_min();
}
-
-/*****************************************************************************/
-
-
-struct wbxng_table_entry {
- wbxng_key key;
- boost::weak_ptr<wbxng> value;
-
- wbxng_table_entry(const wbxng_key &_key, boost::weak_ptr<wbxng> _value)
- : key(_key), value(_value) {}
-};
-
-typedef std::vector<wbxng_table_entry> wbxng_table;
-
-static boost::mutex s_table_mutex;
-static wbxng_table s_table;
-
-static wbxng_sptr
-_get_or_make_wbxng(usrp_basic_sptr usrp, int which)
+double
+wbxng_base::freq_max()
{
- wbxng_key key = {usrp->serial_number(), which};
+ throw std::runtime_error("freq_max called from wbxng_base\n");
+ //return d_common->freq_max();
+}
- boost::mutex::scoped_lock guard(s_table_mutex);
+// ----------------------------------------------------------------
- for (wbxng_table::iterator p = s_table.begin(); p != s_table.end();){
- if (p->value.expired()) // weak pointer is now dead
- p = s_table.erase(p); // erase it
- else {
- if (key == p->key){ // found it
- return wbxng_sptr(p->value);
- }
- else
- ++p; // keep looking
- }
+wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on)
+ : wbxng_base(_usrp, which, _power_on)
+{
+ /*
+ @param usrp: instance of usrp.sink_c
+ @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
+ */
+
+ if(which == 0) {
+ d_spi_enable = SPI_ENABLE_TX_A;
+ }
+ else {
+ d_spi_enable = SPI_ENABLE_TX_B;
}
- // We don't have the wbxng we're looking for
+ d_common = new adf4350(_usrp, d_which, d_spi_enable);
+
+ // power up the transmit side, but don't enable the mixer
+ /*
+ usrp()->_write_oe(d_which,(POWER_UP|RX_TXN|ENABLE), 0xffff);
+ usrp()->write_io(d_which, (power_on()|RX_TXN), (POWER_UP|RX_TXN|ENABLE));
+ set_lo_offset(4e6);
- // create a new one and stick it in the table.
- wbxng_sptr r(new wbxng(usrp, which));
- wbxng_table_entry t(key, r);
- s_table.push_back(t);
+ set_gain((gain_min() + gain_max()) / 2.0); // initialize gain
+ */
+}
- return r;
+wbxng_base_tx::~wbxng_base_tx()
+{
+ shutdown();
}
-/*****************************************************************************/
+void
+wbxng_base_tx::shutdown()
+{
+ // fprintf(stderr, "wbxng_base_tx::shutdown d_is_shutdown = %d\n", d_is_shutdown);
+ if (!d_is_shutdown){
+ d_is_shutdown = true;
+ // do whatever there is to do to shutdown
-db_wbxng_base::db_wbxng_base(usrp_basic_sptr usrp, int which)
- : db_base(usrp, which)
-{
- /*
- * Abstract base class for all wbxng boards.
- *
- * Derive board specific subclasses from db_wbxng_base_{tx,rx}
- *
- * @param usrp: instance of usrp.source_c
- * @param which: which side: 0 or 1 corresponding to side A or B respectively
- * @type which: int
- */
+ // Power down and leave the T/R switch in the R position
+ //usrp()->write_io(d_which, (power_off()|RX_TXN), (POWER_UP|RX_TXN|ENABLE));
+
+ // Power down VCO/PLL
+ d_PD = 3;
- d_wbxng = _get_or_make_wbxng(usrp, which);
+ _write_control(_compute_control_reg());
+ _enable_refclk(false); // turn off refclk
+ set_auto_tr(false);
+ }
}
-db_wbxng_base::~db_wbxng_base()
+bool
+wbxng_base_tx::set_auto_tr(bool on)
{
+ bool ok = true;
+ /*
+ if(on) {
+ ok &= set_atr_mask (RX_TXN | ENABLE);
+ ok &= set_atr_txval(0 | ENABLE);
+ ok &= set_atr_rxval(RX_TXN | 0);
+ }
+ else {
+ ok &= set_atr_mask (0);
+ ok &= set_atr_txval(0);
+ ok &= set_atr_rxval(0);
+ }
+ */
+ return ok;
}
-void
-db_wbxng_base::shutdown_common()
+bool
+wbxng_base_tx::set_enable(bool on)
{
- // If the usrp_basic in the wbxng is the same as the usrp_basic
- // in the daughterboard, shutdown the wbxng now (when only one of Tx
- // and Rx is open, this is always true).
+ /*
+ Enable transmitter if on is true
+ */
- if (d_wbxng->usrp() == usrp()){
- //std::cerr << "db_wbxng_base::shutdown_common: same -> shutting down\n";
- d_wbxng->shutdown();
+ int v;
+ //int mask = RX_TXN | ENABLE_5 | ENABLE_33;
+ if(on) {
+ v = ENABLE_5 | ENABLE_33;
}
else {
- //std::cerr << "db_wbxng_base::shutdown_common: different -> ignoring\n";
+ v = RX_TXN;
}
+ throw std::runtime_error("set_enable called from wbxng_base_tx\n");
+ //return usrp()->write_io(d_which, v, mask);
}
-struct freq_result_t
-db_wbxng_base::set_freq(double target_freq)
+float
+wbxng_base_tx::gain_min()
{
- /*
- * @returns (ok, actual_baseband_freq) where:
- * ok is True or False and indicates success or failure,
- * actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
- */
- return d_wbxng->set_freq(target_freq+d_lo_offset);
+ return usrp()->pga_max();
}
-bool
-db_wbxng_base::is_quadrature()
+float
+wbxng_base_tx::gain_max()
{
- /*
- * Return True if this board requires both I & Q analog channels.
- *
- * This bit of info is useful when setting up the USRP Rx mux register.
- */
- return true;
+ return usrp()->pga_max();
}
-double
-db_wbxng_base::freq_min()
+float
+wbxng_base_tx::gain_db_per_step()
{
- return 2.4e9;
+ return 1;
}
-double
-db_wbxng_base::freq_max()
+bool
+wbxng_base_tx::set_gain(float gain)
{
- return 6.0e9;
+ /*
+ Set the gain.
+
+ @param gain: gain in decibels
+ @returns True/False
+ */
+ return _set_pga(usrp()->pga_max());
}
-/******************************************************************************/
+/**************************************************************************/
-db_wbxng_tx::db_wbxng_tx(usrp_basic_sptr usrp, int which)
- : db_wbxng_base(usrp, which)
+wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on)
+ : wbxng_base(_usrp, which, _power_on)
{
- set_lo_offset(LO_OFFSET);
- //printf("db_wbxng_tx::db_wbxng_tx\n");
+ /*
+ @param usrp: instance of usrp.source_c
+ @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
+ */
+
+ if(which == 0) {
+ d_spi_enable = SPI_ENABLE_RX_A;
+ }
+ else {
+ d_spi_enable = SPI_ENABLE_RX_B;
+ }
+
+ d_common = new adf4350(_usrp, d_which, d_spi_enable);
+
+ /*
+ usrp()->_write_oe(d_which, (POWER_UP|RX2_RX1N|ENABLE), 0xffff);
+ usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE),
+ (POWER_UP|RX2_RX1N|ENABLE));
+
+ // set up for RX on TX/RX port
+ select_rx_antenna("TX/RX");
+
+ bypass_adc_buffers(true);
+
+ set_lo_offset(-4e6);
+ */
}
-db_wbxng_tx::~db_wbxng_tx()
+wbxng_base_rx::~wbxng_base_rx()
{
shutdown();
}
void
-db_wbxng_tx::shutdown()
+wbxng_base_rx::shutdown()
{
+ // fprintf(stderr, "wbxng_base_rx::shutdown d_is_shutdown = %d\n", d_is_shutdown);
+
if (!d_is_shutdown){
d_is_shutdown = true;
- shutdown_common();
+ // do whatever there is to do to shutdown
+
+ // Power down
+ //usrp()->common_write_io(C_RX, d_which, power_off(), (POWER_UP|ENABLE));
+
+ // Power down VCO/PLL
+ d_PD = 3;
+
+
+ // fprintf(stderr, "wbxng_base_rx::shutdown before _write_control\n");
+ //_write_control(_compute_control_reg());
+
+ // fprintf(stderr, "wbxng_base_rx::shutdown before _enable_refclk\n");
+ //_enable_refclk(false); // turn off refclk
+
+ // fprintf(stderr, "wbxng_base_rx::shutdown before set_auto_tr\n");
+ //set_auto_tr(false);
+
+ // fprintf(stderr, "wbxng_base_rx::shutdown after set_auto_tr\n");
}
}
-float
-db_wbxng_tx::gain_min()
+bool
+wbxng_base_rx::set_auto_tr(bool on)
{
- return 0;
+ //bool ok = true;
+ /*
+ if(on) {
+ ok &= set_atr_mask (ENABLE);
+ ok &= set_atr_txval( 0);
+ ok &= set_atr_rxval(ENABLE);
+ }
+ else {
+ ok &= set_atr_mask (0);
+ ok &= set_atr_txval(0);
+ ok &= set_atr_rxval(0);
+ }
+ */
+ return true;
}
-float
-db_wbxng_tx::gain_max()
+/* *** TODO *** Defined select_rx_antenna twice?
+bool
+wbxng_base_rx::select_rx_antenna(int which_antenna)
{
- return 30;
-}
+ **COMMENT**
+ Specify which antenna port to use for reception.
+ @param which_antenna: either 'TX/RX' or 'RX2'
+ **COMMENT**
-float
-db_wbxng_tx::gain_db_per_step()
-{
- return (30.0/63.0);
+ if(which_antenna == 0) {
+ usrp()->write_io(d_which, 0,RX2_RX1N);
+ }
+ else if(which_antenna == 1) {
+ usrp()->write_io(d_which, RX2_RX1N, RX2_RX1N);
+ }
+ else {
+ return false;
+ // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
+ }
+ return true;
}
+*/
bool
-db_wbxng_tx::set_gain(float gain)
+wbxng_base_rx::select_rx_antenna(const std::string &which_antenna)
{
- return d_wbxng->set_tx_gain(gain);
+ /*
+ Specify which antenna port to use for reception.
+ @param which_antenna: either 'TX/RX' or 'RX2'
+ */
+
+ /*
+ if(which_antenna == "TX/RX") {
+ usrp()->write_io(d_which, 0, RX2_RX1N);
+ }
+ else if(which_antenna == "RX2") {
+ usrp()->write_io(d_which, RX2_RX1N, RX2_RX1N);
+ }
+ else {
+ // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n");
+ return false;
+ }
+ */
+ return true;
}
bool
-db_wbxng_tx::i_and_q_swapped()
+wbxng_base_rx::set_gain(float gain)
{
- return true;
+ /*
+ Set the gain.
+
+ @param gain: gain in decibels
+ @returns True/False
+ */
+
+ /*
+ // clamp gain
+ gain = std::max(gain_min(), std::min(gain, gain_max()));
+
+ float pga_gain, agc_gain;
+ float V_maxgain, V_mingain, V_fullscale, dac_value;
+
+ float maxgain = gain_max() - usrp()->pga_max();
+ float mingain = gain_min();
+ if(gain > maxgain) {
+ pga_gain = gain-maxgain;
+ assert(pga_gain <= usrp()->pga_max());
+ agc_gain = maxgain;
+ }
+ else {
+ pga_gain = 0;
+ agc_gain = gain;
+ }
+
+ V_maxgain = .2;
+ V_mingain = 1.2;
+ V_fullscale = 3.3;
+ dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale;
+
+ assert(dac_value>=0 && dac_value<4096);
+
+ return (usrp()->write_aux_dac(d_which, 0, int(dac_value))
+ && _set_pga(int(pga_gain)));
+ */
+ return false;
}
+// ----------------------------------------------------------------
-/******************************************************************************/
+db_wbxng_tx::db_wbxng_tx(usrp_basic_sptr usrp, int which)
+ : wbxng_base_tx(usrp, which)
+{
+}
+db_wbxng_tx::~db_wbxng_tx()
+{
+}
-db_wbxng_rx::db_wbxng_rx(usrp_basic_sptr usrp, int which)
- : db_wbxng_base(usrp, which)
+/*
+bool
+db_wbxng_tx::_compute_regs(double freq, int &retR, int &retcontrol,
+ int &retN, double &retfreq)
{
- /*
- * @param usrp: instance of usrp.source_c
- * @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
- */
- set_lo_offset(LO_OFFSET);
- //printf("db_wbxng_rx:d_wbxng_rx\n");
+ return d_common->_compute_regs(_refclk_freq(), freq, retR,
+ retcontrol, retN, retfreq);
}
+*/
-db_wbxng_rx::~db_wbxng_rx()
+
+db_wbxng_rx::db_wbxng_rx(usrp_basic_sptr usrp, int which)
+ : wbxng_base_rx(usrp, which)
{
- shutdown();
+ set_gain((gain_min() + gain_max()) / 2.0); // initialize gain
}
-void
-db_wbxng_rx::shutdown()
+db_wbxng_rx::~db_wbxng_rx()
{
- if (!d_is_shutdown){
- d_is_shutdown = true;
- shutdown_common();
- }
}
float
db_wbxng_rx::gain_min()
{
- return 0.0;
+ return usrp()->pga_min();
}
float
db_wbxng_rx::gain_max()
{
- return 92.0;
+ return usrp()->pga_max()+70;
}
float
db_wbxng_rx::gain_db_per_step()
{
- return 1;
+ return 0.05;
+}
+
+
+bool
+db_wbxng_rx::i_and_q_swapped()
+{
+ return true;
}
+/*
bool
-db_wbxng_rx::set_gain(float gain)
+db_wbxng_rx::_compute_regs(double freq, int &retR, int &retcontrol,
+ int &retN, double &retfreq)
{
- return d_wbxng->set_rx_gain(gain);
+ return d_common->_compute_regs(_refclk_freq(), freq, retR,
+ retcontrol, retN, retfreq);
}
+*/
+