From 052e7a2c880edbc0dd55dc05d2758d3730cf9cb8 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 17 Aug 2009 23:30:01 -0700 Subject: Initial compile of wbxng, properly sets db IDs --- usrp/host/lib/db_wbxng.cc | 809 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 809 insertions(+) create mode 100644 usrp/host/lib/db_wbxng.cc (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc new file mode 100644 index 000000000..53ec27afc --- /dev/null +++ b/usrp/host/lib/db_wbxng.cc @@ -0,0 +1,809 @@ +// +// Copyright 2008,2009 Free Software Foundation, Inc. +// +// This file is part of GNU Radio +// +// GNU Radio 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 asversion 3, or (at your option) +// any later version. +// +// GNU Radio 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 GNU Radio; see the file COPYING. If not, write to +// the Free Software Foundation, Inc., 51 Franklin Street, +// Boston, MA 02110-1301, USA. + +#include +#include +#include +#include +#include +#include + +#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) +{ + // 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 + + // Use MSB with no header + 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 + + /* + // 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); + */ +} + +wbxng::~wbxng() +{ + //printf("wbxng::destructor\n"); + shutdown(); +} + +void +wbxng::shutdown() +{ + 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); + */ + } +} + + +void +wbxng::set_reg_standby() +{ + d_reg_standby = ((d_mimo<<17) | + (1<<16) | + (1<<6) | + (1<<5) | + (1<<4) | 2); + //send_reg(d_reg_standby); +} + +void +wbxng::set_reg_int_divider() +{ + d_reg_int_divider = (((d_frac_div & 0x03)<<16) | + (d_int_div<<4) | 3); + //send_reg(d_reg_int_divider); +} + +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() +{ + // FIXME do calibration + d_reg_cal = (1<<14)|6; + //send_reg(d_reg_cal); +} + +void +wbxng::set_reg_lpf() +{ + 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); +} + +void +wbxng::set_reg_rxrssi_ctrl() +{ + 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); +} + +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); +} + +void +wbxng::set_reg_pabias() +{ + d_reg_pabias = ( + (d_pabias_delay<<10) | + (d_pabias<<4) | 10); + //send_reg(d_reg_pabias); +} + +void +wbxng::set_reg_rxgain() +{ + d_reg_rxgain = ( + (d_rx_rf_gain<<9) | + (d_rx_bb_gain<<4) | 11); + //send_reg(d_reg_rxgain); +} + +void +wbxng::set_reg_txgain() +{ + 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); +} + +// ---------------------------------------------------------------- + +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; + + /* + // 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); + */ + + //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; + + //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); + } + return args; +} + +bool +wbxng::lock_detect() +{ + /* + @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; + } + else { // Give it a second chance + if(usrp()->common_read_io(C_RX, d_which) & LOCKDET) + return true; + else + return false; + } + */ + 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(); + + return true; +} + +bool +wbxng::set_tx_gain(float gain) +{ + 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; +} + + +/*****************************************************************************/ + + +struct wbxng_table_entry { + wbxng_key key; + boost::weak_ptr value; + + wbxng_table_entry(const wbxng_key &_key, boost::weak_ptr _value) + : key(_key), value(_value) {} +}; + +typedef std::vector 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) +{ + wbxng_key key = {usrp->serial_number(), which}; + + 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 + } + } + + // We don't have the wbxng we're looking for + + // 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); + + return r; +} + + +/*****************************************************************************/ + + +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 + */ + + d_wbxng = _get_or_make_wbxng(usrp, which); +} + +db_wbxng_base::~db_wbxng_base() +{ +} + +void +db_wbxng_base::shutdown_common() +{ + // 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). + + if (d_wbxng->usrp() == usrp()){ + //std::cerr << "db_wbxng_base::shutdown_common: same -> shutting down\n"; + d_wbxng->shutdown(); + } + else { + //std::cerr << "db_wbxng_base::shutdown_common: different -> ignoring\n"; + } +} + +struct freq_result_t +db_wbxng_base::set_freq(double target_freq) +{ + /* + * @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); +} + +bool +db_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; +} + +double +db_wbxng_base::freq_min() +{ + return 2.4e9; +} + +double +db_wbxng_base::freq_max() +{ + return 6.0e9; +} + + +/******************************************************************************/ + + +db_wbxng_tx::db_wbxng_tx(usrp_basic_sptr usrp, int which) + : db_wbxng_base(usrp, which) +{ + set_lo_offset(LO_OFFSET); + //printf("db_wbxng_tx::db_wbxng_tx\n"); +} + +db_wbxng_tx::~db_wbxng_tx() +{ + shutdown(); +} + +void +db_wbxng_tx::shutdown() +{ + if (!d_is_shutdown){ + d_is_shutdown = true; + shutdown_common(); + } +} + +float +db_wbxng_tx::gain_min() +{ + return 0; +} + +float +db_wbxng_tx::gain_max() +{ + return 30; +} + +float +db_wbxng_tx::gain_db_per_step() +{ + return (30.0/63.0); +} + +bool +db_wbxng_tx::set_gain(float gain) +{ + return d_wbxng->set_tx_gain(gain); +} + +bool +db_wbxng_tx::i_and_q_swapped() +{ + return true; +} + + +/******************************************************************************/ + + +db_wbxng_rx::db_wbxng_rx(usrp_basic_sptr usrp, int which) + : db_wbxng_base(usrp, which) +{ + /* + * @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"); +} + +db_wbxng_rx::~db_wbxng_rx() +{ + shutdown(); +} + +void +db_wbxng_rx::shutdown() +{ + if (!d_is_shutdown){ + d_is_shutdown = true; + shutdown_common(); + } +} + +float +db_wbxng_rx::gain_min() +{ + return 0.0; +} + +float +db_wbxng_rx::gain_max() +{ + return 92.0; +} + +float +db_wbxng_rx::gain_db_per_step() +{ + return 1; +} + +bool +db_wbxng_rx::set_gain(float gain) +{ + return d_wbxng->set_rx_gain(gain); +} -- cgit From ba4f8351cc3b74895f3f0a880ad25f51652cd94b Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Fri, 21 Aug 2009 10:08:44 -0700 Subject: Clean build --- usrp/host/lib/db_wbxng.cc | 1061 +++++++++++++++++++-------------------------- 1 file changed, 442 insertions(+), 619 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') 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 +#include #include -#include -#include -#include -#include - -#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 value; - - wbxng_table_entry(const wbxng_key &_key, boost::weak_ptr _value) - : key(_key), value(_value) {} -}; - -typedef std::vector 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); } +*/ + -- cgit From 16951928760f44b729f3f67e3c6c279c3fef28c1 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Fri, 21 Aug 2009 15:16:18 -0700 Subject: twiddling gpio successfully --- usrp/host/lib/db_wbxng.cc | 75 ++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 37 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index e911c9d03..ccad3cb41 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -46,7 +46,7 @@ wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on) d_first = true; d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0; - usrp()->_write_oe(d_which, 0, 0xffff); // turn off all outputs + usrp()->_write_oe(d_which, 1, 0xffff); // turn off all outputs _enable_refclk(false); // disable refclk set_auto_tr(false); @@ -125,11 +125,13 @@ wbxng_base::_lock_detect() @returns: the value of the VCO/PLL lock detect bit. @rtype: 0 or 1 */ - /* - if(usrp()->read_io(d_which) & PLL_LOCK_DETECT) { + + if(d_common->_get_locked()){ return true; } else { // Give it a second chance + return false; + /* // FIXME: make portable sleep timespec t; t.tv_sec = 0; @@ -142,8 +144,9 @@ wbxng_base::_lock_detect() else { return false; } + */ } - */ + throw std::runtime_error("_lock_detect called from wbxng_base\n"); } @@ -199,14 +202,17 @@ wbxng_base::set_freq(double freq) actual_baseband_freq is the RF frequency that corresponds to DC in the IF. */ - struct freq_result_t args = {false, 0}; + freq_t int_freq = (freq_t) freq; + bool ok = d_common->_set_freq(int_freq); + double freq_result = (double) d_common->_get_freq(); + struct freq_result_t args = {ok, freq_result}; // 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; + //freq += d_lo_offset; //int R, control, N; //double actual_freq; @@ -252,15 +258,13 @@ wbxng_base::is_quadrature() double wbxng_base::freq_min() { - throw std::runtime_error("freq_min called from wbxng_base\n"); - //return d_common->freq_min(); + return (double) d_common->_get_min_freq(); } double wbxng_base::freq_max() { - throw std::runtime_error("freq_max called from wbxng_base\n"); - //return d_common->freq_max(); + return (double) d_common->_get_max_freq(); } // ---------------------------------------------------------------- @@ -283,13 +287,11 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) 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); + usrp()->_write_oe(d_which,(RX_TXN|ENABLE_33|ENABLE_5), 0xffff); + usrp()->write_io(d_which, (power_on()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5)); + //set_lo_offset(4e6); - set_gain((gain_min() + gain_max()) / 2.0); // initialize gain - */ + //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain } wbxng_base_tx::~wbxng_base_tx() @@ -308,12 +310,14 @@ wbxng_base_tx::shutdown() // do whatever there is to do to shutdown // 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)); + usrp()->write_io(d_which, (power_off()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5)); + /* // Power down VCO/PLL d_PD = 3; _write_control(_compute_control_reg()); + */ _enable_refclk(false); // turn off refclk set_auto_tr(false); } @@ -325,8 +329,8 @@ 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_mask (RX_TXN | ENABLE_33 | ENABLE_5); + ok &= set_atr_txval(0 | ENABLE_33 | ENABLE_5); ok &= set_atr_rxval(RX_TXN | 0); } else { @@ -346,15 +350,14 @@ wbxng_base_tx::set_enable(bool on) */ int v; - //int mask = RX_TXN | ENABLE_5 | ENABLE_33; + int mask = RX_TXN | ENABLE_5 | ENABLE_33; if(on) { v = ENABLE_5 | ENABLE_33; } else { v = RX_TXN; } - throw std::runtime_error("set_enable called from wbxng_base_tx\n"); - //return usrp()->write_io(d_which, v, mask); + return usrp()->write_io(d_which, v, mask); } float @@ -408,16 +411,16 @@ wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on) 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)); + usrp()->_write_oe(d_which, (RX2_RX1N|ENABLE_33|ENABLE_5), 0xffff); + usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE_33|ENABLE_5), + (RX2_RX1N|ENABLE_33|ENABLE_5)); // set up for RX on TX/RX port select_rx_antenna("TX/RX"); bypass_adc_buffers(true); + /* set_lo_offset(-4e6); */ } @@ -437,7 +440,7 @@ wbxng_base_rx::shutdown() // do whatever there is to do to shutdown // Power down - //usrp()->common_write_io(C_RX, d_which, power_off(), (POWER_UP|ENABLE)); + usrp()->common_write_io(C_RX, d_which, power_off(), (ENABLE_33|ENABLE_5)); // Power down VCO/PLL d_PD = 3; @@ -447,10 +450,10 @@ wbxng_base_rx::shutdown() //_write_control(_compute_control_reg()); // fprintf(stderr, "wbxng_base_rx::shutdown before _enable_refclk\n"); - //_enable_refclk(false); // turn off refclk + _enable_refclk(false); // turn off refclk // fprintf(stderr, "wbxng_base_rx::shutdown before set_auto_tr\n"); - //set_auto_tr(false); + set_auto_tr(false); // fprintf(stderr, "wbxng_base_rx::shutdown after set_auto_tr\n"); } @@ -462,9 +465,9 @@ wbxng_base_rx::set_auto_tr(bool on) //bool ok = true; /* if(on) { - ok &= set_atr_mask (ENABLE); + ok &= set_atr_mask (ENABLE_33|ENABLE_5); ok &= set_atr_txval( 0); - ok &= set_atr_rxval(ENABLE); + ok &= set_atr_rxval(ENABLE_33|ENABLE_5); } else { ok &= set_atr_mask (0); @@ -475,14 +478,13 @@ wbxng_base_rx::set_auto_tr(bool on) return true; } -/* *** TODO *** Defined select_rx_antenna twice? bool wbxng_base_rx::select_rx_antenna(int which_antenna) { - **COMMENT** + /* Specify which antenna port to use for reception. @param which_antenna: either 'TX/RX' or 'RX2' - **COMMENT** + */ if(which_antenna == 0) { usrp()->write_io(d_which, 0,RX2_RX1N); @@ -496,7 +498,6 @@ wbxng_base_rx::select_rx_antenna(int which_antenna) } return true; } -*/ bool wbxng_base_rx::select_rx_antenna(const std::string &which_antenna) @@ -506,7 +507,7 @@ wbxng_base_rx::select_rx_antenna(const std::string &which_antenna) @param which_antenna: either 'TX/RX' or 'RX2' */ - /* + if(which_antenna == "TX/RX") { usrp()->write_io(d_which, 0, RX2_RX1N); } @@ -517,7 +518,7 @@ wbxng_base_rx::select_rx_antenna(const std::string &which_antenna) // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n"); return false; } - */ + return true; } -- cgit From e4b5ce36f60652dba15ff4124b347c9a8b725d05 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Sun, 23 Aug 2009 17:40:43 -0700 Subject: Able to tune RX VCO, observe R and N divider output on MUXOUT --- usrp/host/lib/db_wbxng.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index ccad3cb41..1c7b23265 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -43,10 +43,11 @@ wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on) @type which: int */ + usrp()->_write_oe(d_which, 0, 0xffff); // turn off all outputs + d_first = true; d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0; - usrp()->_write_oe(d_which, 1, 0xffff); // turn off all outputs _enable_refclk(false); // disable refclk set_auto_tr(false); @@ -202,11 +203,14 @@ wbxng_base::set_freq(double freq) actual_baseband_freq is the RF frequency that corresponds to DC in the IF. */ - freq_t int_freq = (freq_t) freq; + freq_t int_freq = (freq_t) (freq/1000); bool ok = d_common->_set_freq(int_freq); - double freq_result = (double) d_common->_get_freq(); + double freq_result = (double) d_common->_get_freq()*1000; struct freq_result_t args = {ok, freq_result}; + fprintf(stderr,"Setting WBXNG frequency, requested %d, obtained %f, lock_detect %d\n", + int_freq*1000, freq_result, _lock_detect()); + // 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 @@ -287,8 +291,8 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) 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,(RX_TXN|ENABLE_33|ENABLE_5), 0xffff); - usrp()->write_io(d_which, (power_on()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which,(PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); //set_lo_offset(4e6); //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain @@ -310,7 +314,7 @@ wbxng_base_tx::shutdown() // do whatever there is to do to shutdown // Power down and leave the T/R switch in the R position - usrp()->write_io(d_which, (power_off()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_off()|RX_TXN), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); /* // Power down VCO/PLL @@ -352,7 +356,7 @@ wbxng_base_tx::set_enable(bool on) int v; int mask = RX_TXN | ENABLE_5 | ENABLE_33; if(on) { - v = ENABLE_5 | ENABLE_33; + v = PLL_CE | ENABLE_5 | ENABLE_33; } else { v = RX_TXN; @@ -411,9 +415,8 @@ wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on) d_common = new adf4350(_usrp, d_which, d_spi_enable); - usrp()->_write_oe(d_which, (RX2_RX1N|ENABLE_33|ENABLE_5), 0xffff); - usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE_33|ENABLE_5), - (RX2_RX1N|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which, (RX2_RX1N|ENABLE_33|ENABLE_5), (RX2_RX1N|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE_33|ENABLE_5), (RX2_RX1N|ENABLE_33|ENABLE_5)); // set up for RX on TX/RX port select_rx_antenna("TX/RX"); -- cgit From a85e0396f5adf1c4d72d81cbbead02e139a6d5af Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 24 Aug 2009 16:20:03 -0700 Subject: Locking, controllable synthesizer on TX and RX set Charge Pump Current (Icp) per design guide on schem set R divider to 3, so that PFD inputs are ~21MHz set RF output enable even when looking for AUX --- usrp/host/lib/db_wbxng.cc | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index 1c7b23265..970d8efd6 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -203,13 +203,19 @@ wbxng_base::set_freq(double freq) actual_baseband_freq is the RF frequency that corresponds to DC in the IF. */ - freq_t int_freq = (freq_t) (freq/1000); + freq_t int_freq = freq_t(freq); bool ok = d_common->_set_freq(int_freq); - double freq_result = (double) d_common->_get_freq()*1000; + double freq_result = (double) d_common->_get_freq(); struct freq_result_t args = {ok, freq_result}; + /* Wait before reading Lock Detect*/ + timespec t; + t.tv_sec = 0; + t.tv_nsec = 10000000; + nanosleep(&t, NULL); + fprintf(stderr,"Setting WBXNG frequency, requested %d, obtained %f, lock_detect %d\n", - int_freq*1000, freq_result, _lock_detect()); + int_freq, freq_result, _lock_detect()); // 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 @@ -291,8 +297,8 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) 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,(PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); - usrp()->write_io(d_which, (power_on()|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which,(PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); //set_lo_offset(4e6); //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain @@ -314,7 +320,7 @@ wbxng_base_tx::shutdown() // do whatever there is to do to shutdown // Power down and leave the T/R switch in the R position - usrp()->write_io(d_which, (power_off()|RX_TXN), (PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_off()|RX_TXN), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); /* // Power down VCO/PLL @@ -354,9 +360,9 @@ wbxng_base_tx::set_enable(bool on) */ int v; - int mask = RX_TXN | ENABLE_5 | ENABLE_33; + int mask = PLL_PDBRF | PLL_PDBRF | RX_TXN | ENABLE_5 | ENABLE_33; if(on) { - v = PLL_CE | ENABLE_5 | ENABLE_33; + v = PLL_PDBRF | PLL_CE | ENABLE_5 | ENABLE_33; } else { v = RX_TXN; -- cgit From 9aff67eeedcaf7c0fcca0fe2410ec2a3dbd4ea02 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Fri, 18 Sep 2009 18:28:02 -0700 Subject: First Functional TX modulator --- usrp/host/lib/db_wbxng.cc | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index 970d8efd6..8a03cfbac 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -21,6 +21,7 @@ #include #include #include +#include // d'board i/o pin defs // Tx and Rx have shared defs, but different i/o regs @@ -28,7 +29,7 @@ #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 TXMOD_EN (1 << 4) #define PLL_CE (1 << 3) #define PLL_PDBRF (1 << 2) #define PLL_MUXOUT (1 << 1) @@ -204,8 +205,8 @@ wbxng_base::set_freq(double freq) */ freq_t int_freq = freq_t(freq); - bool ok = d_common->_set_freq(int_freq); - double freq_result = (double) d_common->_get_freq(); + bool ok = d_common->_set_freq(int_freq*2); + double freq_result = (double) d_common->_get_freq()/2.0; struct freq_result_t args = {ok, freq_result}; /* Wait before reading Lock Detect*/ @@ -268,13 +269,13 @@ wbxng_base::is_quadrature() double wbxng_base::freq_min() { - return (double) d_common->_get_min_freq(); + return (double) d_common->_get_min_freq()/2.0; } double wbxng_base::freq_max() { - return (double) d_common->_get_max_freq(); + return (double) d_common->_get_max_freq()/2.0; } // ---------------------------------------------------------------- @@ -297,8 +298,9 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) 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,(PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); - usrp()->write_io(d_which, (power_on()|PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which,(RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5), (RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5), (RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5)); + fprintf(stderr,"Setting WBXNG TXMOD on"); //set_lo_offset(4e6); //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain @@ -320,12 +322,12 @@ wbxng_base_tx::shutdown() // do whatever there is to do to shutdown // Power down and leave the T/R switch in the R position - usrp()->write_io(d_which, (power_off()|RX_TXN), (PLL_PDBRF|PLL_CE|RX_TXN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_off()|RX_TXN), (RX_TXN|ENABLE_33|ENABLE_5)); - /* // Power down VCO/PLL - d_PD = 3; + d_common->_enable(false); + /* _write_control(_compute_control_reg()); */ _enable_refclk(false); // turn off refclk @@ -337,7 +339,6 @@ bool wbxng_base_tx::set_auto_tr(bool on) { bool ok = true; - /* if(on) { ok &= set_atr_mask (RX_TXN | ENABLE_33 | ENABLE_5); ok &= set_atr_txval(0 | ENABLE_33 | ENABLE_5); @@ -348,7 +349,6 @@ wbxng_base_tx::set_auto_tr(bool on) ok &= set_atr_txval(0); ok &= set_atr_rxval(0); } - */ return ok; } @@ -360,9 +360,9 @@ wbxng_base_tx::set_enable(bool on) */ int v; - int mask = PLL_PDBRF | PLL_PDBRF | RX_TXN | ENABLE_5 | ENABLE_33; + int mask = RX_TXN | ENABLE_5 | ENABLE_33; if(on) { - v = PLL_PDBRF | PLL_CE | ENABLE_5 | ENABLE_33; + v = ENABLE_5 | ENABLE_33; } else { v = RX_TXN; @@ -452,8 +452,7 @@ wbxng_base_rx::shutdown() usrp()->common_write_io(C_RX, d_which, power_off(), (ENABLE_33|ENABLE_5)); // Power down VCO/PLL - d_PD = 3; - + d_common->_enable(false); // fprintf(stderr, "wbxng_base_rx::shutdown before _write_control\n"); //_write_control(_compute_control_reg()); @@ -471,8 +470,7 @@ wbxng_base_rx::shutdown() bool wbxng_base_rx::set_auto_tr(bool on) { - //bool ok = true; - /* + bool ok = true; if(on) { ok &= set_atr_mask (ENABLE_33|ENABLE_5); ok &= set_atr_txval( 0); @@ -483,7 +481,6 @@ wbxng_base_rx::set_auto_tr(bool on) ok &= set_atr_txval(0); ok &= set_atr_rxval(0); } - */ return true; } -- cgit From 48e2124c1eac6806d3259964d80348ad1d64214c Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Tue, 22 Sep 2009 14:07:42 -0700 Subject: Enabled RX Baseband --- usrp/host/lib/db_wbxng.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index 8a03cfbac..aa61012e7 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -29,6 +29,7 @@ #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 RXBB_EN (1 << 4) #define TXMOD_EN (1 << 4) #define PLL_CE (1 << 3) #define PLL_PDBRF (1 << 2) @@ -421,8 +422,9 @@ wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on) d_common = new adf4350(_usrp, d_which, d_spi_enable); - usrp()->_write_oe(d_which, (RX2_RX1N|ENABLE_33|ENABLE_5), (RX2_RX1N|ENABLE_33|ENABLE_5)); - usrp()->write_io(d_which, (power_on()|RX2_RX1N|ENABLE_33|ENABLE_5), (RX2_RX1N|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which, (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5)); + fprintf(stderr,"Setting WBXNG RXBB on"); // set up for RX on TX/RX port select_rx_antenna("TX/RX"); -- cgit From bf0bbd9daf5360b5d1fb5f36dcb968d6bcd0fd60 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Thu, 24 Sep 2009 16:12:26 -0700 Subject: Integrated gain control for TX and RX of wbxng --- usrp/host/lib/db_wbxng.cc | 69 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index aa61012e7..0dd8b0d38 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -36,6 +36,10 @@ #define PLL_MUXOUT (1 << 1) #define PLL_LOCK_DETECT (1 << 0) +// RX Attenuator constants +#define ATTN_SHIFT 8 +#define ATTN_MASK (63 << ATTN_SHIFT) + wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on) : db_base(_usrp, which), d_power_on(_power_on) { @@ -243,7 +247,6 @@ wbxng_base::set_freq(double freq) bool wbxng_base::_set_pga(float pga_gain) { - /* if(d_which == 0) { usrp()->set_pga(0, pga_gain); usrp()->set_pga(1, pga_gain); @@ -252,7 +255,6 @@ wbxng_base::_set_pga(float pga_gain) usrp()->set_pga(2, pga_gain); usrp()->set_pga(3, pga_gain); } - */ return true; } @@ -304,7 +306,7 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) fprintf(stderr,"Setting WBXNG TXMOD on"); //set_lo_offset(4e6); - //set_gain((gain_min() + gain_max()) / 2.0); // initialize gain + set_gain((gain_min() + gain_max()) / 2.0); // initialize gain } wbxng_base_tx::~wbxng_base_tx() @@ -380,7 +382,7 @@ wbxng_base_tx::gain_min() float wbxng_base_tx::gain_max() { - return usrp()->pga_max(); + return usrp()->pga_max() + 25.0; } float @@ -398,7 +400,35 @@ wbxng_base_tx::set_gain(float gain) @param gain: gain in decibels @returns True/False */ - return _set_pga(usrp()->pga_max()); + + // 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 = 0.7; + V_mingain = 1.4; + V_fullscale = 3.3; + dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale; + + fprintf(stderr, "TXGAIN: %f dB, Dac Code: %d, Voltage: %f\n", gain, int(dac_value), float((dac_value/4096.0)*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))); } @@ -422,8 +452,8 @@ wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on) d_common = new adf4350(_usrp, d_which, d_spi_enable); - usrp()->_write_oe(d_which, (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5)); - usrp()->write_io(d_which, (power_on()|RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5)); + usrp()->_write_oe(d_which, (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5)); + usrp()->write_io(d_which, (power_on()|RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5)); fprintf(stderr,"Setting WBXNG RXBB on"); // set up for RX on TX/RX port @@ -540,12 +570,10 @@ wbxng_base_rx::set_gain(float gain) @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(); @@ -559,17 +587,16 @@ wbxng_base_rx::set_gain(float gain) 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 _set_attn(maxgain-agc_gain) && _set_pga(int(pga_gain)); +} - return (usrp()->write_aux_dac(d_which, 0, int(dac_value)) - && _set_pga(int(pga_gain))); - */ - return false; +bool +wbxng_base_rx::_set_attn(float attn) +{ + int attn_code = int(floor(attn/0.5)); + unsigned int iobits = (~attn_code) << ATTN_SHIFT; + fprintf(stderr, "Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x \n", attn, attn_code, iobits & ATTN_MASK, ATTN_MASK); + return usrp()->write_io(d_which, iobits, ATTN_MASK); } // ---------------------------------------------------------------- @@ -613,7 +640,7 @@ db_wbxng_rx::gain_min() float db_wbxng_rx::gain_max() { - return usrp()->pga_max()+70; + return usrp()->pga_max()+30.5; } float @@ -626,7 +653,7 @@ db_wbxng_rx::gain_db_per_step() bool db_wbxng_rx::i_and_q_swapped() { - return true; + return false; } /* -- cgit From 69caa7dce5a58b39614b1aba99c2dd71b38af322 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 6 Oct 2009 17:50:59 -0700 Subject: Clean up for work-in-progress Copyright updates Trailing whitespace cleanup Move private headers out of install Use standard include guards Code cleanup --- usrp/host/lib/db_wbxng.cc | 227 ++++++---------------------------------------- 1 file changed, 29 insertions(+), 198 deletions(-) (limited to 'usrp/host/lib/db_wbxng.cc') diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc index 0dd8b0d38..c23fc47ed 100644 --- a/usrp/host/lib/db_wbxng.cc +++ b/usrp/host/lib/db_wbxng.cc @@ -1,25 +1,25 @@ // -// Copyright 2008 Free Software Foundation, Inc. -// +// Copyright 2008,2009 Free Software Foundation, Inc. +// // This file is part of GNU Radio -// +// // GNU Radio 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 asversion 3, or (at your option) // any later version. -// +// // GNU Radio 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 GNU Radio; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. #include -#include +#include "db_wbxng_adf4350.h" #include #include @@ -61,143 +61,8 @@ wbxng_base::wbxng_base(usrp_basic_sptr _usrp, int which, int _power_on) wbxng_base::~wbxng_base() { - delete d_common; -} - -void -wbxng_base::_write_all(int R, int control, int N) -{ - /* - 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_base::_write_control(int control) -{ - //_write_it((control & ~0x3) | 0); -} - -void -wbxng_base::_write_R(int R) -{ - //_write_it((R & ~0x3) | 1); -} - -void -wbxng_base::_write_N(int N) -{ - //_write_it((N & ~0x3) | 2); -} - -void -wbxng_base::_write_it(int v) -{ - 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); -} - -bool -wbxng_base::_lock_detect() -{ - /* - @returns: the value of the VCO/PLL lock detect bit. - @rtype: 0 or 1 - */ - - if(d_common->_get_locked()){ - return true; - } - else { // Give it a second chance - return false; - /* - // 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"); -} - -/* -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"); -} -*/ - -int -wbxng_base::_compute_control_reg() -{ - throw std::runtime_error("_compute_control_reg called from wbxng_base\n"); - //return d_common->_compute_control_reg(); -} - -int -wbxng_base::_refclk_divisor() -{ - throw std::runtime_error("_refclk_divisor called from wbxng_base\n"); - //return d_common->_refclk_divisor(); -} - -double -wbxng_base::_refclk_freq() -{ - throw std::runtime_error("_refclk_divisor called from wbxng_base\n"); - // *** TODO *** Magic Number 64e6? - //return 64e6/_refclk_divisor(); + if (d_common) + delete d_common; } struct freq_result_t @@ -220,27 +85,17 @@ wbxng_base::set_freq(double freq) t.tv_nsec = 10000000; nanosleep(&t, NULL); - fprintf(stderr,"Setting WBXNG frequency, requested %d, obtained %f, lock_detect %d\n", + fprintf(stderr,"Setting WBXNG frequency, requested %d, obtained %f, lock_detect %d\n", int_freq, freq_result, _lock_detect()); + // FIXME // 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; - - //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; } @@ -263,7 +118,7 @@ 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; @@ -290,7 +145,7 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _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; } @@ -299,11 +154,11 @@ wbxng_base_tx::wbxng_base_tx(usrp_basic_sptr _usrp, int which, int _power_on) } d_common = new adf4350(_usrp, d_which, d_spi_enable); - - // power up the transmit side, but don't enable the mixer + + // FIXME: power up the transmit side, but don't enable the mixer usrp()->_write_oe(d_which,(RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5), (RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5)); usrp()->write_io(d_which, (power_on()|RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5), (RX_TXN|TXMOD_EN|ENABLE_33|ENABLE_5)); - fprintf(stderr,"Setting WBXNG TXMOD on"); + fprintf(stderr,"Setting WBXNG TXMOD on"); //set_lo_offset(4e6); set_gain((gain_min() + gain_max()) / 2.0); // initialize gain @@ -329,7 +184,7 @@ wbxng_base_tx::shutdown() // Power down VCO/PLL d_common->_enable(false); - + /* _write_control(_compute_control_reg()); */ @@ -396,11 +251,11 @@ wbxng_base_tx::set_gain(float gain) { /* Set the gain. - + @param gain: gain in decibels @returns True/False */ - + // clamp gain gain = std::max(gain_min(), std::min(gain, gain_max())); @@ -418,7 +273,7 @@ wbxng_base_tx::set_gain(float gain) pga_gain = 0; agc_gain = gain; } - + V_maxgain = 0.7; V_mingain = 1.4; V_fullscale = 3.3; @@ -454,14 +309,14 @@ wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on) usrp()->_write_oe(d_which, (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5)); usrp()->write_io(d_which, (power_on()|RX2_RX1N|RXBB_EN|ENABLE_33|ENABLE_5), (RX2_RX1N|RXBB_EN|ATTN_MASK|ENABLE_33|ENABLE_5)); - fprintf(stderr,"Setting WBXNG RXBB on"); - + fprintf(stderr,"Setting WBXNG RXBB on"); + // set up for RX on TX/RX port select_rx_antenna("TX/RX"); - + bypass_adc_buffers(true); - /* + /* set_lo_offset(-4e6); */ } @@ -532,7 +387,6 @@ wbxng_base_rx::select_rx_antenna(int which_antenna) } else { return false; - // throw std::invalid_argument("which_antenna must be either 'TX/RX' or 'RX2'\n"); } return true; } @@ -545,7 +399,7 @@ wbxng_base_rx::select_rx_antenna(const std::string &which_antenna) @param which_antenna: either 'TX/RX' or 'RX2' */ - + if(which_antenna == "TX/RX") { usrp()->write_io(d_which, 0, RX2_RX1N); } @@ -553,10 +407,9 @@ wbxng_base_rx::select_rx_antenna(const std::string &which_antenna) 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; } @@ -565,11 +418,11 @@ wbxng_base_rx::set_gain(float gain) { /* Set the gain. - + @param gain: gain in decibels @returns True/False */ - + // clamp gain gain = std::max(gain_min(), std::min(gain, gain_max())); @@ -586,7 +439,7 @@ wbxng_base_rx::set_gain(float gain) pga_gain = 0; agc_gain = gain; } - + return _set_attn(maxgain-agc_gain) && _set_pga(int(pga_gain)); } @@ -610,17 +463,6 @@ db_wbxng_tx::~db_wbxng_tx() { } -/* -bool -db_wbxng_tx::_compute_regs(double freq, int &retR, int &retcontrol, - int &retN, double &retfreq) -{ - return d_common->_compute_regs(_refclk_freq(), freq, retR, - retcontrol, retN, retfreq); -} -*/ - - db_wbxng_rx::db_wbxng_rx(usrp_basic_sptr usrp, int which) : wbxng_base_rx(usrp, which) { @@ -655,14 +497,3 @@ db_wbxng_rx::i_and_q_swapped() { return false; } - -/* -bool -db_wbxng_rx::_compute_regs(double freq, int &retR, int &retcontrol, - int &retN, double &retfreq) -{ - return d_common->_compute_regs(_refclk_freq(), freq, retR, - retcontrol, retN, retfreq); -} -*/ - -- cgit