commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r9418 - gnuradio/branches/developers/trondeau/dbs/usrp


From: trondeau
Subject: [Commit-gnuradio] r9418 - gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy
Date: Mon, 25 Aug 2008 19:27:05 -0600 (MDT)

Author: trondeau
Date: 2008-08-25 19:27:04 -0600 (Mon, 25 Aug 2008)
New Revision: 9418

Added:
   gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.cc
   gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.h
Log:
wip: WBX class; needs some inheritance rework.

Added: gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.cc
===================================================================
--- gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.cc    
                        (rev 0)
+++ gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.cc    
2008-08-26 01:27:04 UTC (rev 9418)
@@ -0,0 +1,878 @@
+/* -*- c++ -*- */
+//
+// Copyright 2008 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 <db_wbx.h>
+#include <stdexcept>
+#include <cmath>
+
+// d'board i/o pin defs
+
+// TX IO Pins
+#define TX_POWER        (1 << 0)  // TX Side Power
+#define RX_TXN          (1 << 1)  // T/R antenna switch for TX/RX port
+#define TX_ENB_MIX      (1 << 2)  // Enable IQ mixer
+#define TX_ENB_VGA      (1 << 3)
+
+// RX IO Pins
+#define RX2_RX1N        (1 << 0)  // antenna switch between RX2 and TX/RX port
+#define RXENABLE        (1 << 1)  // enables mixer
+#define PLL_LOCK_DETECT (1 << 2)  // Muxout pin from PLL -- MUST BE INPUT
+#define MReset          (1 << 3)  // NB6L239 Master Reset, asserted low
+#define SELA0           (1 << 4)  // NB6L239 SelA0
+#define SELA1           (1 << 5)  // NB6L239 SelA1
+#define SELB0           (1 << 6)  // NB6L239 SelB0
+#define SELB1           (1 << 7)  // NB6L239 SelB1
+#define PLL_ENABLE      (1 << 8)  // CE Pin on PLL
+#define AUX_SCLK        (1 << 9)  // ALT SPI SCLK
+#define AUX_SDO         (1 << 10) // ALT SPI SDO
+#define AUX_SEN         (1 << 11) // ALT SPI SEN
+
+
+wbx_base::wbx_base(usrp_basic *usrp, int which)
+  : db_base(usrp, which)
+{
+  /*
+   * @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_first = true;
+  d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0;
+
+  // FIXME -- the write reg functions don't work with 0xffff for masks
+  
_rx_write_oe(int(PLL_ENABLE|MReset|SELA0|SELA1|SELB0|SELB1|RX2_RX1N|RXENABLE), 
0x7fff);
+  _rx_write_io((PLL_ENABLE|MReset|0|RXENABLE), 
(PLL_ENABLE|MReset|RX2_RX1N|RXENABLE));
+
+  _tx_write_oe((TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA), 0x7fff);
+  _tx_write_io((0|RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA));  // TX 
off, TR switch set to RX
+
+  if(d_which == 0) {
+    d_spi_enable = SPI_ENABLE_RX_A;
+  }
+  else {
+    d_spi_enable = SPI_ENABLE_RX_B;
+  }
+
+  set_auto_tr(false);
+        
+}
+
+wbx_base::~wbx_base()
+{        
+  //d_usrp->write_io(d_which, d_power_off, POWER_UP)   // turn off power to 
board
+  //d_usrp->_write_oe(d_which, 0, 0xffff)   // turn off all outputs
+  set_auto_tr(false);
+}
+
+bool
+wbx_base::_lock_detect()
+{
+  /*
+   * @returns: the value of the VCO/PLL lock detect bit.
+   * @rtype: 0 or 1
+   */
+
+  if(_rx_read_io() & PLL_LOCK_DETECT) {
+    return true;
+  }
+  else {     // Give it a second chance
+    if(_rx_read_io() & PLL_LOCK_DETECT) {
+      return true;
+    }
+    else {
+      return false;
+    }
+  }
+}
+
+bool 
+wbx_base::_tx_write_oe(int value, int mask)
+{
+  int reg = (d_which == 0 ? FR_OE_0 : FR_OE_2);
+  return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 
0xffff));
+}
+
+bool 
+wbx_base::_rx_write_oe(int value, int mask)
+{
+  int reg = (d_which == 0 ? FR_OE_1 : FR_OE_3);
+  return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 
0xffff));
+}
+
+bool
+wbx_base::_tx_write_io(int value, int mask)
+{
+  int reg = (d_which == 0 ? FR_IO_0 : FR_IO_2);
+  return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 
0xffff));
+}
+
+bool
+wbx_base::_rx_write_io(int value, int mask)
+{
+  int reg = (d_which == 0 ? FR_IO_1 : FR_IO_3);
+  return d_usrp->_write_fpga_reg(reg, ((mask & 0xffff) << 16) | (value & 
0xffff));
+}
+
+bool
+wbx_base::_rx_read_io()
+{
+  int reg = (d_which == 0 ? FR_RB_IO_RX_A_IO_TX_A : FR_RB_IO_RX_B_IO_TX_B);
+  int t = d_usrp->_read_fpga_reg(reg);
+  return (t >> 16) & 0xffff;
+}
+
+bool
+wbx_base::_tx_read_io()
+{
+  int reg = (d_which == 0 ? FR_RB_IO_RX_A_IO_TX_A : FR_RB_IO_RX_B_IO_TX_B);
+  int t = d_usrp->_read_fpga_reg(reg);
+  return (t & 0xffff);
+}
+
+bool
+wbx_base::_compute_regs(float freq)
+{
+  /*
+   * Determine values of registers, along with actual freq.
+   * 
+   * @param freq: target frequency in Hz
+   * @type freq: float
+   * @returns: (R, N, func, init, actual_freq)
+   * @rtype: tuple(int, int, int, int, float)
+   * 
+   * Override this in derived classes.
+   */
+  throw std::runtime_error("_compute_regs called from base class\n");
+}
+
+float
+wbx_base::_refclk_freq()
+{
+  return (float)(d_usrp->fpga_master_clock_freq())/_refclk_divisor();
+}
+
+int
+wbx_base::_refclk_divisor()
+{
+  /*
+   * Return value to stick in REFCLK_DIVISOR register
+   */
+  return 1;
+}
+
+struct freq_result_t
+wbx_base::set_freq(float 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.
+   */
+  throw std::runtime_error("set_freq called from base class\n");
+}
+
+float
+wbx_base::gain_min()
+{
+  throw std::runtime_error("gain_min called from base class\n");
+}
+
+float
+wbx_base::gain_max()
+{
+  throw std::runtime_error("gain_max called from base class\n");
+}
+
+float
+wbx_base::gain_db_per_step()
+{
+  throw std::runtime_error("gain_db_per_step called from base class\n");
+}
+
+bool
+wbx_base::set_gain(float gain)
+{
+  /*
+   * Set the gain.
+   * 
+   * @param gain:  gain in decibels
+   * @returns True/False
+   */
+  throw std::runtime_error("set_gain called from base class\n");
+}
+
+bool
+wbx_base::_set_pga(float pga_gain)
+{
+  bool ok;
+  if(d_which == 0) {
+    ok  = d_usrp->set_pga(0, pga_gain);
+    ok |= d_usrp->set_pga(1, pga_gain);
+  }
+  else {
+    ok  = d_usrp->set_pga(2, pga_gain);
+    ok |= d_usrp->set_pga(3, pga_gain);
+  }
+  return ok;
+}
+
+bool
+wbx_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;
+}
+
+void
+wbx_base::_write_it(int v)
+{
+  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);
+  d_usrp->_write_spi(0, d_spi_enable, d_spi_format, s);
+}
+
+
+/****************************************************************************/
+
+
+wbx_base_tx::wbx_base_tx(usrp_basic *usrp, int which)
+  : wbx_base(usrp, which)
+{        
+  /*
+   * @param usrp: instance of usrp.sink_c
+   * @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
+   */
+  
+  // power up the transmit side, NO -- but set antenna to receive
+  d_usrp->write_io(d_which, (TX_POWER), (TX_POWER|RX_TXN));
+  d_lo_offset = 0e6;
+  
+  // Gain is not set by the PGA, but the PGA must be set at max gain in the TX
+  _set_pga(d_usrp->pga_max());
+}
+
+wbx_base_tx::~wbx_base_tx()
+{
+  // Power down and leave the T/R switch in the R position
+  d_usrp->write_io(d_which, (RX_TXN), (TX_POWER|RX_TXN|TX_ENB_MIX|TX_ENB_VGA));
+}
+
+void
+wbx_base_tx::set_auto_tr(bool on)
+{
+  if(on) {
+    set_atr_mask (RX_TXN);
+    set_atr_txval(0);
+    set_atr_rxval(RX_TXN);
+  }
+  else {
+    set_atr_mask (0);
+    set_atr_txval(0);
+    set_atr_rxval(0);
+  }
+}
+
+void
+wbx_base_tx::set_enable(bool on)
+{
+  /*
+   * Enable transmitter if on is True
+   */
+
+  int mask = RX_TXN|TX_ENB_MIX|TX_ENB_VGA;
+  //printf("HERE!!!!\n");
+  if(on) {
+    d_usrp->write_io(d_which, TX_ENB_MIX|TX_ENB_VGA, mask);
+  }
+  else {
+    d_usrp->write_io(d_which, RX_TXN, mask);
+  }
+}
+
+void
+wbx_base_tx::set_lo_offset(float offset)
+{
+  /*
+   * Set amount by which LO is offset from requested tuning frequency.
+   * 
+   * @param offset: offset in Hz
+   */
+  
+  d_lo_offset = offset;
+}
+
+float
+wbx_base_tx::lo_offset()
+{
+  /*
+   * Get amount by which LO is offset from requested tuning frequency.
+   * 
+   * @returns Offset in Hz
+   */
+
+  return d_lo_offset;
+}
+
+
+/****************************************************************************/
+
+
+wbx_base_rx::wbx_base_rx(usrp_basic *usrp, int which)
+  : wbx_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 up for RX on TX/RX port
+  select_rx_antenna("TX/RX");
+  
+  bypass_adc_buffers(true);
+
+  d_lo_offset = 0.0;
+}
+
+wbx_base_rx::~wbx_base_rx()
+{
+  // Power down
+  d_usrp->write_io(d_which, 0, (RXENABLE));
+}
+  
+void
+wbx_base_rx::set_auto_tr(bool on)
+{
+  if(on) {
+    // FIXME: where does ENABLE come from?
+    //set_atr_mask (ENABLE);
+    set_atr_txval(     0);
+    //set_atr_rxval(ENABLE);
+  }
+  else {
+    set_atr_mask (0);
+    set_atr_txval(0);
+    set_atr_rxval(0);
+  }
+}
+
+void
+wbx_base_rx::select_rx_antenna(int which_antenna)
+{
+  /*
+   * Specify which antenna port to use for reception.
+   * @param which_antenna: either 'TX/RX' or 'RX2'
+   */
+  
+  if(which_antenna == 0) {
+    d_usrp->write_io(d_which, 0,        RX2_RX1N);
+  }
+  else if(which_antenna == 1) {
+    d_usrp->write_io(d_which, RX2_RX1N, RX2_RX1N);
+  }
+  else {
+    throw std::invalid_argument("which_antenna must be either 'TX/RX' or 
'RX2'\n");
+  }
+}
+
+void
+wbx_base_rx::select_rx_antenna(const std::string &which_antenna)
+{
+  if(which_antenna == "TX/RX") {
+    select_rx_antenna(0);
+  }
+  else if(which_antenna == "RX2") {
+    select_rx_antenna(1);
+  }
+  else {
+    throw std::invalid_argument("which_antenna must be either 'TX/RX' or 
'RX2'\n");
+  }
+}
+
+bool
+wbx_base_rx::set_gain(float gain)
+{
+  /*
+   * Set the gain.
+   * 
+   * @param gain:  gain in decibels
+   * @returns True/False
+   */
+  
+  float pga_gain, agc_gain;
+  float maxgain = gain_max() - d_usrp->pga_max();
+  float mingain = gain_min();
+  if(gain > maxgain) {
+    pga_gain = gain-maxgain;
+    assert(pga_gain <= d_usrp->pga_max());
+    agc_gain = maxgain;
+  }
+  else {
+    pga_gain = 0;
+    agc_gain = gain;
+  }
+   
+  float V_maxgain = .2;
+  float V_mingain = 1.2;
+  float V_fullscale = 3.3;
+  float dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + 
V_mingain)*4096/V_fullscale;
+
+  assert(dac_value>=0 && dac_value<4096);
+
+  return d_usrp->write_aux_dac(d_which, 0, (int)(dac_value)) && 
_set_pga((int)(pga_gain));
+}
+
+void
+wbx_base_rx::set_lo_offset(float offset)
+{
+  /*
+   * Set amount by which LO is offset from requested tuning frequency.
+   * 
+   * @param offset: offset in Hz
+   */
+  d_lo_offset = offset;
+}
+
+float
+wbx_base_rx::lo_offset()
+{
+  /*
+   * Get amount by which LO is offset from requested tuning frequency.
+   * 
+   * @returns Offset in Hz
+   */
+  return d_lo_offset;
+}
+
+bool
+wbx_base_rx::i_and_q_swapped()
+{
+  /*
+   * Return True if this is a quadrature device and ADC 0 is Q.
+   */
+  return false;
+}
+
+
+/****************************************************************************/
+
+_ADF410X_common::_ADF410X_common()
+{
+  // R-Register Common Values
+  d_R_RSV = 0;    // bits 23,22,21
+  d_LDP = 1;      // bit 20     Lock detect in 5 cycles
+  d_TEST = 0;     // bit 19,18  Normal
+  d_ABP = 0;      // bit 17,16  2.9ns
+    
+  // N-Register Common Values
+  d_N_RSV = 0;    // 23,22
+  d_CP_GAIN = 0;  // 21
+    
+  // Function Register Common Values
+  d_P = 0;        // bits 23,22    0 = 8/9, 1 = 16/17, 2 = 32/33, 3 = 64/65
+  d_PD2 = 0;      // bit  21       Normal operation
+  d_CP2 = 4;      // bits 20,19,18 CP Gain = 5mA
+  d_CP1 = 4;      // bits 17,16,15 CP Gain = 5mA
+  d_TC = 0;       // bits 14-11    PFD Timeout
+  d_FL = 0;       // bit 10,9      Fastlock Disabled
+  d_CP3S = 0;     // bit 8         CP Enabled
+  d_PDP = 0;      // bit 7         Phase detector polarity, Positive=1
+  d_MUXOUT = 1;   // bits 6:4      Digital Lock Detect
+  d_PD1 = 0;      // bit 3         Normal operation
+  d_CR = 0;       // bit 2         Normal operation
+}
+
+_ADF410X_common::~_ADF410X_common()
+{
+}
+
+bool 
+_ADF410X_common::_compute_regs(float freq, int &retR, int &retcontrol, 
+                              int &retN, float &retfreq)
+{
+  /*
+   * Determine values of R, control, and N registers, along with actual freq.
+   * 
+   * @param freq: target frequency in Hz
+   * @type freq: float
+   * @returns: (R, N, control, actual_freq)
+   * @rtype: tuple(int, int, int, float)
+   */
+  
+  //  Band-specific N-Register Values
+  float phdet_freq = _refclk_freq()/d_R_DIV;
+  printf("phdet_freq = %f\n", phdet_freq);
+
+  float desired_n = round(freq*d_freq_mult/phdet_freq);
+  printf("desired_n %f\n", desired_n);
+
+  float actual_freq = desired_n * phdet_freq;
+  printf("actual freq %f\n", actual_freq);
+
+  float B = floor(desired_n/_prescaler());
+  float A = desired_n - _prescaler()*B;
+  printf("A %f B %f\n", A, B);
+
+  d_B_DIV = int(B);    // bits 20:8;
+  d_A_DIV = int(A);    // bit 6:2;
+
+  if(d_B_DIV < d_A_DIV) {
+    retR = 0;
+    retN = 0;
+    retcontrol = 0;
+    retfreq = 0;
+    return false;
+  }
+
+  retR = (d_R_RSV<<21) | (d_LDP<<20) | (d_TEST<<18) |
+    (d_ABP<<16) | (d_R_DIV<<2);
+        
+  retN = (d_N_RSV<<22) | (d_CP_GAIN<<21) | (d_B_DIV<<8) | (d_A_DIV<<2);
+
+  retcontrol = (d_P<<22) | (d_PD2<<21) | (d_CP2<<18) | (d_CP1<<15) | 
+    (d_TC<<11) | (d_FL<<9) | (d_CP3S<<8) | (d_PDP<<7) |
+    (d_MUXOUT<<4) | (d_PD1<<3) | (d_CR<<2);
+  
+  retfreq = actual_freq/d_freq_mult;
+  
+  return true;
+}
+
+void 
+_ADF410X_common::_write_all(int R, int N, int control)
+{
+  /*
+   * Write all PLL registers:
+   *   R counter latch,
+   *   N counter latch,
+   *   Function latch,
+   *   Initialization latch
+   * 
+   * 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 N: 24-bit N counter latch
+   * @type N: int
+   * @param control: 24-bit control latch
+   * @type control: int
+   */
+  static bool first = true;
+
+  timespec t;
+  t.tv_sec = 0;
+  t.tv_nsec = 10000000;
+  
+  _write_R(R);
+  _write_func(control);
+  _write_init(control);
+  if(first) {
+    //time.sleep(0.010);
+    nanosleep(&t, NULL);
+    first = false;
+  }
+  _write_N(N);
+}
+
+void
+_ADF410X_common::_write_R(int R)
+{
+  _write_it((R & ~0x3) | 0);
+}
+
+void
+_ADF410X_common::_write_N(int N)
+{
+  _write_it((N & ~0x3) | 1);
+}
+
+void
+_ADF410X_common::_write_func(int func)
+{
+  _write_it((func & ~0x3) | 2);
+}
+
+void
+_ADF410X_common::_write_init(int init)
+{
+  _write_it((init & ~0x3) | 3);
+}
+
+void
+_ADF410X_common::_write_it(int v)
+{
+  throw std::runtime_error("_write_it called from base class.\n");
+  /*
+  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);
+  d_usrp->_write_spi(0, d_spi_enable, d_spi_format, s);
+  */
+}
+
+int
+_ADF410X_common::_prescaler()
+{
+  if(d_P == 0) {
+    return 8;
+  }
+  else if(d_P == 1) {
+    return 16;
+  }
+  else if(d_P == 2) {
+    return 32;
+  }
+  else if(d_P == 3) {
+    return 64;
+  }
+  else {
+    throw std::invalid_argument("Prescaler out of range\n");
+  }
+}
+
+
+/****************************************************************************/
+
+
+_lo_common::_lo_common()
+  : _ADF410X_common()
+{
+  // Band-specific R-Register Values
+  d_R_DIV = 4;    // bits 15:2
+  
+  // Band-specific C-Register values
+  d_P = 0;        // bits 23,22   0 = Div by 8/9
+  d_CP2 = 4;      // bits 19:17
+  d_CP1 = 4;      // bits 16:14
+  
+  // Band specifc N-Register Values
+  d_DIVSEL = 0;   // bit 23
+  d_DIV2 = 0;     // bit 22
+  d_CPGAIN = 0;   // bit 21
+  d_freq_mult = 1;
+  
+  d_div = 1;
+  d_aux_div = 2;
+  d_main_div = 0;
+}
+
+_lo_common::~_lo_common()
+{
+}
+
+float
+_lo_common::freq_min()
+{
+  return 50e6;
+}
+
+float
+_lo_common::freq_max()
+{
+  return 1000e6;
+}
+
+void
+_lo_common::set_divider(int main_or_aux, int divisor)
+{
+  if(main_or_aux == 0) {
+    if((divisor != 1) || (divisor != 2) || (divisor != 4) || (divisor != 8)) {
+      throw std::invalid_argument("Main Divider Must be 1, 2, 4, or 8\n");
+    }
+    d_main_div = (int)(log10(divisor)/log10(2.0));
+  }
+  else if(main_or_aux == 1) {
+    if((divisor != 2) || (divisor != 4) || (divisor != 8) || (divisor != 16)) {
+      throw std::invalid_argument("Aux Divider Must be 2, 4, 8 or 16\n");
+    }
+    d_main_div = (int)(log10(divisor/2.0)/log10(2.0));
+  }   
+  else {
+    throw std::invalid_argument("main_or_aux must be 'main' or 'aux'\n");
+  }
+  
+  int vala = d_main_div*SELA0;
+  int valb = d_aux_div*SELB0;
+  int mask = SELA0|SELA1|SELB0|SELB1;
+  
+  _rx_write_io((vala | valb), mask);
+}
+
+void
+_lo_common::set_divider(const std::string &main_or_aux, int divisor)
+{
+  if(main_or_aux == "main") {
+    set_divider(0, divisor);
+  }
+  else if(main_or_aux == "aux") {
+    set_divider(1, divisor);
+  }
+  else {
+    throw std::invalid_argument("main_or_aux must be 'main' or 'aux'\n");
+  }
+}
+
+struct freq_result_t
+_lo_common::set_freq(float freq)
+{
+  struct freq_result_t ret;
+  
+  if(freq < 20e6 or freq > 1200e6) {
+    throw std::invalid_argument("Requested frequency out of range\n");
+  }
+
+  int div = 1;
+  float lo_freq = freq * 2;
+  while((lo_freq < 1e9) && (div < 8)) {
+    div = div * 2;
+    lo_freq = lo_freq * 2;
+  }
+  
+  printf("For RF freq of %f, we set DIV=%d and LO Freq=%f\n", freq, div, 
lo_freq);
+
+  set_divider("main", div);
+  set_divider("aux", div*2);
+  
+  int R, N, control;
+  float actual_freq;
+  _compute_regs(lo_freq, R, N, control, actual_freq);
+  
+  printf("R %d N %d control %d actual freq %f\n", R, N, control, actual_freq);
+  if(R==0) {
+    ret.ok = false;
+    ret.baseband_freq = 0.0;
+    return ret;
+  }
+  _write_all(R, N, control);
+  
+  ret.ok = _lock_detect();
+  ret.baseband_freq = actual_freq/div/2;
+  return ret;
+}
+        
+
+/****************************************************************************/
+
+
+db_wbx_lo_tx::db_wbx_lo_tx(usrp_basic *usrp, int which)
+  : _lo_common(),
+    wbx_base_tx(usrp, which)
+{
+}
+
+db_wbx_lo_tx::~db_wbx_lo_tx()
+{
+}
+
+float
+db_wbx_lo_tx::gain_min()
+{
+  return -56.0;
+}
+
+float
+db_wbx_lo_tx::gain_max()
+{
+  return 0.0;
+}
+
+float
+db_wbx_lo_tx::gain_db_per_step()
+{
+  return 0.1;
+}
+
+bool
+db_wbx_lo_tx::set_gain(float gain)
+{
+  /*
+   * Set the gain.
+   * 
+   * @param gain:  gain in decibels
+   * @returns True/False
+   */
+
+  float txvga_gain;
+  float maxgain = gain_max();
+  float mingain = gain_min();
+  if(gain > maxgain) {
+    txvga_gain = maxgain;
+  }
+  else if(gain < mingain) {
+    txvga_gain = mingain;
+  }
+  else {
+    txvga_gain = gain;
+  }
+
+  float V_maxgain = 1.4;
+  float V_mingain = 0.1;
+  float V_fullscale = 3.3;
+  float dac_value = ((txvga_gain-mingain)*(V_maxgain-V_mingain)/
+                    (maxgain-mingain) + V_mingain)*4096/V_fullscale;
+
+  assert(dac_value>=0 && dac_value<4096);
+  printf("DAC value %f\n", dac_value);
+
+  return d_usrp->write_aux_dac(d_which, 1, (int)(dac_value));
+}
+
+/****************************************************************************/
+
+
+db_wbx_lo_rx::db_wbx_lo_rx(usrp_basic *usrp, int which)
+  : _lo_common(),
+    wbx_base_rx(usrp, which)    
+{
+}
+
+db_wbx_lo_rx::~db_wbx_lo_rx()
+{
+}
+
+float
+db_wbx_lo_rx::gain_min()
+{
+  return d_usrp->pga_min();
+}
+
+float
+db_wbx_lo_rx::gain_max()
+{
+  return d_usrp->pga_max() + 45;
+}
+
+float
+db_wbx_lo_rx::gain_db_per_step()
+{
+  return 0.05;
+}
+

Added: gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.h
===================================================================
--- gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.h     
                        (rev 0)
+++ gnuradio/branches/developers/trondeau/dbs/usrp/host/lib/legacy/db_wbx.h     
2008-08-26 01:27:04 UTC (rev 9418)
@@ -0,0 +1,203 @@
+/* -*- c++ -*- */
+//
+// Copyright 2008 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.
+
+#ifndef DB_WBX_H
+#define DB_WBX_H
+
+#include <db_base.h>
+#include <boost/shared_ptr.hpp>
+
+
+/*
+  A few comments about the WBX boards:
+  They are half-duplex.  I.e., transmit and receive are mutually exclusive.
+  There is a single LO for both the Tx and Rx sides.
+  The the shared control signals are hung off of the Rx side.
+  The shared io controls are duplexed onto the Rx side pins.
+  The wbx_high d'board always needs to be in 'auto_tr_mode'
+*/
+
+
+class wbx_base : public db_base
+{
+  /*
+   * Abstract base class for all wbx boards.
+   * 
+   * Derive board specific subclasses from db_wbx_base_{tx,rx}
+   */
+
+public:
+  wbx_base(usrp_basic *usrp, int which);
+  ~wbx_base();
+  
+  struct freq_result_t set_freq(float freq);
+  float gain_min();
+  float gain_max();
+  float gain_db_per_step();
+  bool set_gain(float gain);  
+  bool is_quadrature();
+  void _write_it(int v);
+
+protected:
+  bool _lock_detect();
+
+  // FIXME: After testing, replace these with usrp_basic::common_write_io/oe
+  bool _tx_write_oe(int value, int mask);
+  bool _rx_write_oe(int value, int mask);
+  bool _tx_write_io(int value, int mask);
+  bool _rx_write_io(int value, int mask);
+  bool _rx_read_io();
+  bool _tx_read_io();
+  bool  _compute_regs(float freq);
+  float _refclk_freq();
+  int _refclk_divisor();
+
+  bool _set_pga(float pga_gain);
+
+  bool d_first;
+  int d_spi_format;
+  int d_spi_enable;
+  float d_lo_offset;
+};
+
+
+/****************************************************************************/
+
+
+class wbx_base_tx : public wbx_base
+{
+public:
+  wbx_base_tx(usrp_basic *usrp, int which);
+  ~wbx_base_tx();
+
+  void set_auto_tr(bool on);
+  void set_enable(bool on);
+  void set_lo_offset(float offset);
+  float lo_offset();
+};
+
+
+/****************************************************************************/
+
+
+class wbx_base_rx : public wbx_base
+{
+public:
+  wbx_base_rx(usrp_basic *usrp, int which);
+  ~wbx_base_rx();
+  
+  void set_auto_tr(bool on);
+  void select_rx_antenna(int which_antenna);
+  void select_rx_antenna(const std::string &which_antenna);
+  bool set_gain(float gain);
+  void set_lo_offset(float offset);
+  float lo_offset();
+  bool i_and_q_swapped();
+};
+
+
+/****************************************************************************/
+
+
+class _ADF410X_common
+{
+public:
+  _ADF410X_common();
+  virtual ~_ADF410X_common();
+  
+  bool _compute_regs(float freq, int &retR, int &retcontrol,
+                    int &retN, float &retfreq);
+  void _write_all(int R, int N, int control);
+  void _write_R(int R);
+  void _write_N(int N);
+  void _write_func(int func);
+  void _write_init(int init);
+  virtual void _write_it(int v);
+  int  _prescaler();
+
+protected:
+  int d_R_RSV, d_LDP, d_TEST, d_ABP;
+  int d_N_RSV, d_CP_GAIN;
+  int d_P, d_PD2, d_CP2, d_CP1, d_TC, d_FL;
+  int d_CP3S, d_PDP, d_MUXOUT, d_PD1, d_CR;
+  int d_R_DIV, d_A_DIV, d_B_DIV;
+  int d_freq_mult;
+
+  int d_spi_format;
+  int d_spi_enable;
+};
+
+
+/****************************************************************************/
+
+
+class _lo_common : public _ADF410X_common
+{
+public:
+  _lo_common();
+  ~_lo_common();
+
+  float freq_min();
+  float freq_max();
+  
+  void set_divider(int main_or_aux, int divisor);
+  void set_divider(const std::string &main_or_aux, int divisor);
+
+  struct freq_result_t set_freq(float freq);
+
+protected:
+  int d_R_DIV, d_P, d_CP2, d_CP1;
+  int d_DIVSEL, d_DIV2, d_CPGAIN;
+  int d_div, d_aux_div, d_main_div;
+};
+        
+
+/****************************************************************************/
+
+
+class db_wbx_lo_tx : public _lo_common, public wbx_base_tx
+{
+public:
+  db_wbx_lo_tx(usrp_basic *usrp, int which);
+  ~db_wbx_lo_tx();
+
+  float gain_min();
+  float gain_max();
+  float gain_db_per_step();
+  bool  set_gain(float gain);
+};
+        
+
+/****************************************************************************/
+
+
+class db_wbx_lo_rx : public _lo_common, public  wbx_base_rx
+{
+public:
+  db_wbx_lo_rx(usrp_basic *usrp, int which);
+  ~db_wbx_lo_rx();
+
+  float gain_min();
+  float gain_max();
+  float gain_db_per_step();
+};
+
+#endif





reply via email to

[Prev in Thread] Current Thread [Next in Thread]