Merge branch 'wip/wbxng' of git@gnuradio.org:jcorgan
authorJohnathan Corgan <jcorgan@corganenterprises.com>
Wed, 7 Oct 2009 01:17:18 +0000 (18:17 -0700)
committerJohnathan Corgan <jcorgan@corganenterprises.com>
Wed, 7 Oct 2009 01:17:18 +0000 (18:17 -0700)
* 'wip/wbxng' of git@gnuradio.org:jcorgan:
  Clean up for work-in-progress
  Integrated gain control for TX and RX of wbxng
  Enabled RX Baseband
  First Functional TX modulator
  Locking, controllable synthesizer on TX and RX
  Able to tune RX VCO, observe R and N divider output on MUXOUT
  twiddling gpio successfully
  Clean build
  Initial compile of wbxng, properly sets db IDs

usrp/host/apps/burn-db-eeprom
usrp/host/include/usrp/Makefile.am
usrp/host/include/usrp/db_wbxng.h [new file with mode: 0644]
usrp/host/lib/Makefile.am
usrp/host/lib/db_boards.cc
usrp/host/lib/db_wbxng.cc [new file with mode: 0644]
usrp/host/lib/db_wbxng_adf4350.cc [new file with mode: 0644]
usrp/host/lib/db_wbxng_adf4350.h [new file with mode: 0644]
usrp/host/lib/db_wbxng_adf4350_regs.cc [new file with mode: 0644]
usrp/host/lib/db_wbxng_adf4350_regs.h [new file with mode: 0644]
usrp/host/lib/usrp_dbid.dat

index 34f4c7015b1580e1a1ba5b81a29503822ba30461..7ff1e973698c5fe453d427d53a3c6b47eb28fbbf 100755 (executable)
@@ -1,24 +1,24 @@
 #!/usr/bin/env python
 #
-# Copyright 2005,2007 Free Software Foundation, Inc.
-# 
+# Copyright 2005,2007,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 version 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.
-# 
+#
 
 from usrpm.usrp_prims import *
 from optparse import OptionParser
@@ -69,6 +69,7 @@ daughterboards = {
     'lftx'            : ((LF_TX, 0x0000),           None),
     'lfrx'            : (None,                      (LF_RX, 0x0000)),
     'wbx_lo'          : ((WBX_LO_TX, 0x0000),       (WBX_LO_RX, 0x0000)),
+    'wbx_ng'          : ((WBX_NG_TX, 0x0000),       (WBX_NG_RX, 0x0000)),
     'xcvr2450'        : ((XCVR2450_TX, 0x0000),       (XCVR2450_RX, 0x0000)),
     'experimental_tx' : ((EXPERIMENTAL_TX, 0x0000), None),
     'experimental_rx' : (None,                      (EXPERIMENTAL_RX, 0x0000)),
@@ -104,11 +105,11 @@ def init_eeprom(u, slot_name, force, dbid, oe):
     if not e:
         print "%s: no d'board, skipped" % (slot_name,)
         return True
-    
+
     if not force and (sum (map (ord, e)) & 0xff) == 0 and ord (e[0]) == 0xDB:
         print "%s: already initialized, skipped" % (slot_name,)
         return True
-        
+
     if not write_dboard_eeprom (u, i2c_addr, dbid, oe):
         print "%s: failed to write d'board EEPROM" % (slot_name,)
         return False
@@ -168,4 +169,4 @@ and at least one side using -A and/or -B."""
 
 if __name__ == "__main__":
     main ()
-    
+
index 769acc77406b7b1ec921bf22bcb28180ebb45a5d..cfce514438397475c08cdf79d20db5140d4a8c11 100644 (file)
@@ -1,23 +1,23 @@
 #
 # Copyright 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 version 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 $(top_srcdir)/Makefile.common
 
@@ -32,7 +32,8 @@ usrpinclude_HEADERS = \
        db_flexrf.h \
        db_flexrf_mimo.h \
        db_tv_rx.h \
-       db_tv_rx_mimo.h \
+       db_tv_rx_mimo.h \
+       db_wbxng.h \
        db_xcvr2450.h \
        libusb_types.h \
        usrp_basic.h \
diff --git a/usrp/host/include/usrp/db_wbxng.h b/usrp/host/include/usrp/db_wbxng.h
new file mode 100644 (file)
index 0000000..8611d47
--- /dev/null
@@ -0,0 +1,115 @@
+/* -*- c++ -*- */
+//
+// Copyright 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.
+
+#ifndef INCLUDED_DB_WBXNG_H
+#define INCLUDED_DB_WBXNG_H
+
+#include <usrp/db_base.h>
+#include <cmath>
+
+class adf4350;
+
+class wbxng_base : public db_base
+{
+public:
+  wbxng_base(usrp_basic_sptr usrp, int which, int _power_on=0);
+  ~wbxng_base();
+
+  struct freq_result_t set_freq(double freq);
+
+  bool  is_quadrature();
+  double freq_min();
+  double freq_max();
+
+protected:
+  bool _lock_detect();
+  bool _set_pga(float pga_gain);
+
+  int power_on() { return d_power_on; }
+  int power_off() { return 0; }
+
+  bool d_first;
+  int  d_spi_format;
+  int  d_spi_enable;
+  int  d_power_on;
+  int  d_PD;
+
+  adf4350 *d_common;
+};
+
+// ----------------------------------------------------------------
+
+class wbxng_base_tx : public wbxng_base
+{
+protected:
+  void shutdown();
+
+public:
+  wbxng_base_tx(usrp_basic_sptr usrp, int which, int _power_on=0);
+  ~wbxng_base_tx();
+
+  float gain_min();
+  float gain_max();
+  float gain_db_per_step();
+
+  bool set_auto_tr(bool on);
+  bool set_enable(bool on);
+  bool set_gain(float gain);
+};
+
+class wbxng_base_rx : public wbxng_base
+{
+protected:
+  void shutdown();
+  bool _set_attn(float attn);
+
+public:
+  wbxng_base_rx(usrp_basic_sptr usrp, int which, int _power_on=0);
+  ~wbxng_base_rx();
+
+  bool set_auto_tr(bool on);
+  bool select_rx_antenna(int which_antenna);
+  bool select_rx_antenna(const std::string &which_antenna);
+  bool set_gain(float gain);
+};
+
+// ----------------------------------------------------------------
+
+class db_wbxng_tx : public wbxng_base_tx
+{
+ public:
+  db_wbxng_tx(usrp_basic_sptr usrp, int which);
+  ~db_wbxng_tx();
+};
+
+class db_wbxng_rx : public wbxng_base_rx
+{
+public:
+  db_wbxng_rx(usrp_basic_sptr usrp, int which);
+  ~db_wbxng_rx();
+
+  float gain_min();
+  float gain_max();
+  float gain_db_per_step();
+  bool i_and_q_swapped();
+};
+
+#endif /* INCLUDED_DB_WBXNG_H */
index 2f8cbe6deeb8c61cab8371641267056c65ecb18b..72312ebbb37b8a8d2f8b70c558d06f4d2d17cc19 100644 (file)
@@ -1,22 +1,22 @@
 #
 #  USRP - Universal Software Radio Peripheral
-# 
+#
 #  Copyright (C) 2003,2004,2006,2007,2008,2009 Free Software Foundation, Inc.
-# 
+#
 #  This program 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 version 3 of the License, or
 #  (at your option) any later version.
-# 
+#
 #  This program 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 this program; if not, write to the Free Software
 #  Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
-# 
+#
 
 include $(top_srcdir)/Makefile.common
 
@@ -122,6 +122,8 @@ libusrp_la_common_SOURCES =                 \
        usrp_local_sighandler.cc        \
        usrp_prims_common.cc            \
        usrp_standard.cc                \
+       db_wbxng_adf4350.cc                     \
+       db_wbxng_adf4350_regs.cc                        \
        db_boards.cc                    \
        db_base.cc                      \
        db_basic.cc                     \
@@ -130,6 +132,7 @@ libusrp_la_common_SOURCES =                 \
        db_flexrf.cc                    \
        db_flexrf_mimo.cc               \
        db_dbs_rx.cc                    \
+       db_wbxng.cc                     \
        db_xcvr2450.cc                  \
        db_dtt754.cc                    \
        db_dtt768.cc                    \
@@ -165,6 +168,8 @@ noinst_HEADERS =                    \
        db_base_impl.h                  \
        db_boards.h                     \
        db_util.h                       \
+       db_wbxng_adf4350.h              \
+       db_wbxng_adf4350_regs.h         \
        fusb.h                          \
        fusb_darwin.h                   \
        fusb_generic.h                  \
index 8ef5bac8b248647bb8d3d234446253b9d5d39483..590d8132d152f02b368c6ee028cf6f28e539d2c8 100644 (file)
@@ -1,19 +1,19 @@
 /* -*- c++ -*- */
 //
 // 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,
@@ -32,6 +32,7 @@
 #include <usrp/db_dbs_rx.h>
 #include <usrp/db_flexrf.h>
 #include <usrp/db_flexrf_mimo.h>
+#include <usrp/db_wbxng.h>
 #include <usrp/db_xcvr2450.h>
 #include <usrp/db_dtt754.h>
 #include <usrp/db_dtt768.h>
@@ -63,7 +64,7 @@ instantiate_dbs(int dbid, usrp_basic_sptr usrp, int which_side)
     db.push_back(db_base_sptr(new db_lf_rx(usrp, which_side, 1)));
     db.push_back(db_base_sptr(new db_lf_rx(usrp, which_side, 2)));
     break;
-    
+
   case(USRP_DBID_DBS_RX):
     db.push_back(db_base_sptr(new db_dbs_rx(usrp, which_side)));
     break;
@@ -184,7 +185,7 @@ instantiate_dbs(int dbid, usrp_basic_sptr usrp, int which_side)
   case(USRP_DBID_XCVR2450_RX):
     db.push_back(db_base_sptr(new db_xcvr2450_rx(usrp, which_side)));
     break;
-  
+
 #if 0  // FIXME wbx doesn't compile
   case(USRP_DBID_WBX_LO_TX):
     db.push_back(db_base_sptr(new db_wbx_lo_tx(usrp, which_side)));
@@ -194,6 +195,13 @@ instantiate_dbs(int dbid, usrp_basic_sptr usrp, int which_side)
     break;
 #endif
 
+  case(USRP_DBID_WBX_NG_TX):
+    db.push_back(db_base_sptr(new db_wbxng_tx(usrp, which_side)));
+    break;
+  case(USRP_DBID_WBX_NG_RX):
+    db.push_back(db_base_sptr(new db_wbxng_rx(usrp, which_side)));
+    break;
+
   case(USRP_DBID_DTT754):
     db.push_back(db_base_sptr(new db_dtt754(usrp, which_side)));
     break;
@@ -210,7 +218,7 @@ instantiate_dbs(int dbid, usrp_basic_sptr usrp, int which_side)
       db.push_back(db_base_sptr(new db_basic_rx(usrp, which_side, 1)));
     }
     break;
-  
+
   case(-2):
   default:
     if (boost::dynamic_pointer_cast<usrp_basic_tx>(usrp)){
diff --git a/usrp/host/lib/db_wbxng.cc b/usrp/host/lib/db_wbxng.cc
new file mode 100644 (file)
index 0000000..38c3a28
--- /dev/null
@@ -0,0 +1,499 @@
+//
+// 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 <usrp/db_wbxng.h>
+#include "db_wbxng_adf4350.h"
+#include <db_base_impl.h>
+#include <stdio.h>
+
+// 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 RXBB_EN         (1 << 4)
+#define TXMOD_EN        (1 << 4)
+#define PLL_CE          (1 << 3)
+#define PLL_PDBRF       (1 << 2)
+#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)
+{
+  /*
+    @param usrp: instance of usrp.source_c
+    @param which: which side: 0 or 1 corresponding to side A or B respectively
+    @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;
+
+  _enable_refclk(false);                // disable refclk
+
+  set_auto_tr(false);
+}
+
+wbxng_base::~wbxng_base()
+{
+  if (d_common)
+    delete d_common;
+}
+
+struct freq_result_t
+wbxng_base::set_freq(double 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.
+  */
+
+  freq_t int_freq = freq_t(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*/
+  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, freq_result, d_common->_get_locked());
+
+  // 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;
+
+  return args;
+}
+
+bool
+wbxng_base::_set_pga(float pga_gain)
+{
+  if(d_which == 0) {
+    usrp()->set_pga(0, pga_gain);
+    usrp()->set_pga(1, pga_gain);
+  }
+  else {
+    usrp()->set_pga(2, pga_gain);
+    usrp()->set_pga(3, pga_gain);
+  }
+  return true;
+}
+
+bool
+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
+wbxng_base::freq_min()
+{
+  return (double) d_common->_get_min_freq()/2.0;
+}
+
+double
+wbxng_base::freq_max()
+{
+  return (double) d_common->_get_max_freq()/2.0;
+}
+
+// ----------------------------------------------------------------
+
+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;
+  }
+
+  d_common = new adf4350(_usrp, d_which, d_spi_enable);
+
+  // 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");
+  //set_lo_offset(4e6);
+
+  set_gain((gain_min() + gain_max()) / 2.0);  // initialize gain
+}
+
+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
+
+    // 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));
+
+    // Power down VCO/PLL
+    d_common->_enable(false);
+
+    /*
+    _write_control(_compute_control_reg());
+    */
+    _enable_refclk(false);                       // turn off refclk
+    set_auto_tr(false);
+  }
+}
+
+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);
+    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;
+}
+
+bool
+wbxng_base_tx::set_enable(bool on)
+{
+  /*
+    Enable transmitter if on is true
+  */
+
+  int v;
+  int mask = RX_TXN | ENABLE_5 | ENABLE_33;
+  if(on) {
+    v = ENABLE_5 | ENABLE_33;
+  }
+  else {
+    v = RX_TXN;
+  }
+  return usrp()->write_io(d_which, v, mask);
+}
+
+float
+wbxng_base_tx::gain_min()
+{
+  return usrp()->pga_max();
+}
+
+float
+wbxng_base_tx::gain_max()
+{
+  return usrp()->pga_max() + 25.0;
+}
+
+float
+wbxng_base_tx::gain_db_per_step()
+{
+  return 1;
+}
+
+bool
+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()));
+
+  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)));
+}
+
+
+/**************************************************************************/
+
+
+wbxng_base_rx::wbxng_base_rx(usrp_basic_sptr _usrp, int which, int _power_on)
+  : wbxng_base(_usrp, which, _power_on)
+{
+  /*
+    @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, (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
+  select_rx_antenna("TX/RX");
+
+  bypass_adc_buffers(true);
+
+  /*
+  set_lo_offset(-4e6);
+  */
+}
+
+wbxng_base_rx::~wbxng_base_rx()
+{
+  shutdown();
+}
+
+void
+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;
+    // do whatever there is to do to shutdown
+
+    // Power down
+    usrp()->common_write_io(C_RX, d_which, power_off(), (ENABLE_33|ENABLE_5));
+
+    // Power down VCO/PLL
+    d_common->_enable(false);
+
+    // 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");
+  }
+}
+
+bool
+wbxng_base_rx::set_auto_tr(bool on)
+{
+  bool ok = true;
+  if(on) {
+    ok &= set_atr_mask (ENABLE_33|ENABLE_5);
+    ok &= set_atr_txval(     0);
+    ok &= set_atr_rxval(ENABLE_33|ENABLE_5);
+  }
+  else {
+    ok &= set_atr_mask (0);
+    ok &= set_atr_txval(0);
+    ok &= set_atr_rxval(0);
+  }
+  return true;
+}
+
+bool
+wbxng_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) {
+    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;
+  }
+  return true;
+}
+
+bool
+wbxng_base_rx::select_rx_antenna(const std::string &which_antenna)
+{
+  /*
+    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 {
+    return false;
+  }
+
+  return true;
+}
+
+bool
+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()));
+
+  float pga_gain, agc_gain;
+
+  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;
+  }
+
+  return _set_attn(maxgain-agc_gain) && _set_pga(int(pga_gain));
+}
+
+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);
+}
+
+// ----------------------------------------------------------------
+
+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)
+  : wbxng_base_rx(usrp, which)
+{
+  set_gain((gain_min() + gain_max()) / 2.0);  // initialize gain
+}
+
+db_wbxng_rx::~db_wbxng_rx()
+{
+}
+
+float
+db_wbxng_rx::gain_min()
+{
+  return usrp()->pga_min();
+}
+
+float
+db_wbxng_rx::gain_max()
+{
+  return usrp()->pga_max()+30.5;
+}
+
+float
+db_wbxng_rx::gain_db_per_step()
+{
+  return 0.05;
+}
+
+
+bool
+db_wbxng_rx::i_and_q_swapped()
+{
+  return false;
+}
diff --git a/usrp/host/lib/db_wbxng_adf4350.cc b/usrp/host/lib/db_wbxng_adf4350.cc
new file mode 100644 (file)
index 0000000..af4eac5
--- /dev/null
@@ -0,0 +1,199 @@
+//
+// Copyright 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.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "db_wbxng_adf4350.h"
+#include <db_base_impl.h>
+#include <stdio.h>
+
+#define INPUT_REF_FREQ FREQ_C(64e6)
+#define DIV_ROUND(num, denom) (((num) + ((denom)/2))/(denom))
+#define FREQ_C(freq) uint64_t(freq)
+#define INPUT_REF_FREQ_2X (2*INPUT_REF_FREQ)                            /* input ref freq with doubler turned on */
+#define MIN_INT_DIV uint16_t(23)                                        /* minimum int divider, prescaler 4/5 only */
+#define MAX_RF_DIV uint8_t(16)                                          /* max rf divider, divides rf output */
+#define MIN_VCO_FREQ FREQ_C(2.2e9)                                      /* minimum vco freq */
+#define MAX_VCO_FREQ FREQ_C(4.4e9)                                      /* minimum vco freq */
+#define MAX_FREQ MAX_VCO_FREQ                                           /* upper bound freq (rf div = 1) */
+#define MIN_FREQ DIV_ROUND(MIN_VCO_FREQ, MAX_RF_DIV)                    /* calculated lower bound freq */
+
+#define CE_PIN        (1 << 3)
+#define PDB_RF_PIN    (1 << 2)
+#define MUX_PIN       (1 << 1)
+#define LD_PIN        (1 << 0)
+
+adf4350::adf4350(usrp_basic_sptr _usrp, int _which, int _spi_enable)
+{
+    /* Initialize the pin directions. */
+
+    d_usrp = _usrp;
+    d_which = _which;
+    d_spi_enable = _spi_enable;
+    d_spi_format = SPI_FMT_MSB | SPI_FMT_HDR_0;
+
+    d_regs = new adf4350_regs(this);
+
+    /* Outputs */
+    d_usrp->_write_oe(d_which, (CE_PIN | PDB_RF_PIN), (CE_PIN | PDB_RF_PIN));
+    d_usrp->write_io(d_which, (0), (CE_PIN | PDB_RF_PIN));
+
+    /* Initialize the pin levels. */
+    _enable(true);
+    /* Initialize the registers. */
+    d_regs->_load_register(5);
+    d_regs->_load_register(4);
+    d_regs->_load_register(3);
+    d_regs->_load_register(2);
+    d_regs->_load_register(1);
+    d_regs->_load_register(0);
+}
+
+adf4350::~adf4350()
+{
+    delete d_regs;
+}
+
+freq_t
+adf4350::_get_max_freq(void)
+{
+    return MAX_FREQ;
+}
+
+freq_t
+adf4350::_get_min_freq(void)
+{
+    return MIN_FREQ;
+}
+
+bool
+adf4350::_get_locked(void)
+{
+    return d_usrp->read_io(d_which) & LD_PIN;
+}
+
+void
+adf4350::_enable(bool enable)
+{
+    if (enable){ /* chip enable */
+        d_usrp->write_io(d_which, (CE_PIN | PDB_RF_PIN), (CE_PIN | PDB_RF_PIN));
+    }else{
+        d_usrp->write_io(d_which, 0, (CE_PIN | PDB_RF_PIN));
+    }
+}
+
+void
+adf4350::_write(uint8_t addr, uint32_t data)
+{
+    data |= addr;
+
+    // create str from data here
+    char s[4];
+    s[0] = (char)((data >> 24) & 0xff);
+    s[1] = (char)((data >> 16) & 0xff);
+    s[2] = (char)((data >>  8) & 0xff);
+    s[3] = (char)(data & 0xff);
+    std::string str(s, 4);
+
+    timespec t;
+    t.tv_sec = 0;
+    t.tv_nsec = 5e6;
+
+    nanosleep(&t, NULL);
+    d_usrp->_write_spi(0, d_spi_enable, d_spi_format, str);
+    nanosleep(&t, NULL);
+
+    //fprintf(stderr, "Wrote to WBXNG SPI address %d with data %8x\n", addr, data);
+    /* pulse latch */
+    //d_usrp->write_io(d_which, 1, LE_PIN);
+    //d_usrp->write_io(d_which, 0, LE_PIN);
+}
+
+bool
+adf4350::_set_freq(freq_t freq)
+{
+    /* Set the frequency by setting int, frac, mod, r, div */
+    if (freq > MAX_FREQ || freq < MIN_FREQ) return false;
+    /* Ramp up the RF divider until the VCO is within range. */
+    d_regs->d_divider_select = 0;
+    while (freq < MIN_VCO_FREQ){
+        freq <<= 1; //double the freq
+        d_regs->d_divider_select++; //double the divider
+    }
+    /* Ramp up the R divider until the N divider is at least the minimum. */
+    //d_regs->d_10_bit_r_counter = INPUT_REF_FREQ*MIN_INT_DIV/freq;
+    d_regs->d_10_bit_r_counter = 2;
+    uint64_t n_mod;
+    do{
+        d_regs->d_10_bit_r_counter++;
+        n_mod = freq;
+        n_mod *= d_regs->d_10_bit_r_counter;
+        n_mod *= d_regs->d_mod;
+        n_mod /= INPUT_REF_FREQ;
+        /* calculate int and frac */
+        d_regs->d_int = n_mod/d_regs->d_mod;
+        d_regs->d_frac = (n_mod - (freq_t)d_regs->d_int*d_regs->d_mod) & uint16_t(0xfff);
+        /*
+        fprintf(stderr,
+            "VCO %lu KHz, Int %u, Frac %u, Mod %u, R %u, Div %u\n",
+            freq, d_regs->d_int, d_regs->d_frac,
+            d_regs->d_mod, d_regs->d_10_bit_r_counter, (1 << d_regs->d_divider_select)
+        );
+        */
+    }while(d_regs->d_int < MIN_INT_DIV);
+    /* calculate the band select so PFD is under 125 KHz */
+    d_regs->d_8_bit_band_select_clock_divider_value = \
+        INPUT_REF_FREQ/(FREQ_C(30e3)*d_regs->d_10_bit_r_counter) + 1;
+    /*
+    fprintf(stderr, "Band Selection: Div %u, Freq %lu\n",
+        d_regs->d_8_bit_band_select_clock_divider_value,
+        INPUT_REF_FREQ/(d_regs->d_8_bit_band_select_clock_divider_value * d_regs->d_10_bit_r_counter) + 1
+    );
+    */
+    d_regs->_load_register(5);
+    d_regs->_load_register(3);
+    d_regs->_load_register(1);
+    /* load involved registers */
+    d_regs->_load_register(2);
+    d_regs->_load_register(4);
+    d_regs->_load_register(0); /* register 0 must be last */
+    return true;
+}
+
+freq_t
+adf4350::_get_freq(void)
+{
+    /* Calculate the freq from int, frac, mod, ref, r, div:
+     *  freq = (int + frac/mod) * (ref/r)
+     * Keep precision by doing multiplies first:
+     *  freq = (((((((int)*mod) + frac)*ref)/mod)/r)/div)
+     */
+    uint64_t temp;
+    temp = d_regs->d_int;
+    temp *= d_regs->d_mod;
+    temp += d_regs->d_frac;
+    temp *= INPUT_REF_FREQ;
+    temp /= d_regs->d_mod;
+    temp /= d_regs->d_10_bit_r_counter;
+    temp /= (1 << d_regs->d_divider_select);
+    return temp;
+}
diff --git a/usrp/host/lib/db_wbxng_adf4350.h b/usrp/host/lib/db_wbxng_adf4350.h
new file mode 100644 (file)
index 0000000..2b0783c
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Copyright 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.
+
+#ifndef INCLUDED_ADF4350_H
+#define INCLUDED_ADF4350_H
+
+#include "db_wbxng_adf4350_regs.h"
+#include <usrp/db_base.h>
+#include <stdint.h>
+
+typedef uint64_t freq_t;
+class adf4350_regs;
+
+class adf4350
+{
+public:
+    adf4350(usrp_basic_sptr _usrp, int _which, int _spi_enable);
+    ~adf4350();
+    void _update();
+    bool _get_locked();
+    void _enable(bool enable);
+    void _write(uint8_t addr, uint32_t data);
+    bool _set_freq(freq_t freq);
+    freq_t _get_freq();
+    freq_t _get_max_freq();
+    freq_t _get_min_freq();
+
+protected:
+    usrp_basic_sptr d_usrp;
+    int d_which;
+    int d_spi_enable;
+    int d_spi_format;
+    adf4350_regs *d_regs;
+};
+
+#endif /* INCLUDED_ADF4350_H */
diff --git a/usrp/host/lib/db_wbxng_adf4350_regs.cc b/usrp/host/lib/db_wbxng_adf4350_regs.cc
new file mode 100644 (file)
index 0000000..11dcf88
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009 Ettus Research LLC
+ */
+
+#include "db_wbxng_adf4350_regs.h"
+#include "db_wbxng_adf4350.h"
+
+//#include "cal_div.h"
+
+/* reg 0 */
+/* reg 1 */
+const uint8_t adf4350_regs::s_prescaler = 0;
+const uint16_t adf4350_regs::s_phase = 0;
+/* reg 2 */
+const uint8_t adf4350_regs::s_low_noise_and_low_spur_modes = 0;
+const uint8_t adf4350_regs::s_muxout = 6;
+const uint8_t adf4350_regs::s_reference_doubler = 0;
+const uint8_t adf4350_regs::s_rdiv2 = 0;
+const uint8_t adf4350_regs::s_double_buff = 0;
+const uint8_t adf4350_regs::s_charge_pump_setting = 5;
+const uint8_t adf4350_regs::s_ldf = 0;
+const uint8_t adf4350_regs::s_ldp = 0;
+const uint8_t adf4350_regs::s_pd_polarity = 1;
+const uint8_t adf4350_regs::s_power_down = 0;
+const uint8_t adf4350_regs::s_cp_three_state = 0;
+const uint8_t adf4350_regs::s_counter_reset = 0;
+/* reg 3 */
+const uint8_t adf4350_regs::s_csr = 0;
+const uint8_t adf4350_regs::s_clk_div_mode = 0;
+const uint16_t adf4350_regs::s_12_bit_clock_divider_value = 0;
+/* reg 4 */
+const uint8_t adf4350_regs::s_feedback_select = 1;
+const uint8_t adf4350_regs::s_vco_power_down = 0;
+const uint8_t adf4350_regs::s_mtld = 0;
+const uint8_t adf4350_regs::s_aux_output_select = 0;
+const uint8_t adf4350_regs::s_aux_output_enable = 1;
+const uint8_t adf4350_regs::s_aux_output_power = 3;
+const uint8_t adf4350_regs::s_rf_output_enable = 1;
+const uint8_t adf4350_regs::s_output_power = 3;
+/* reg 5 */
+const uint8_t adf4350_regs::s_ld_pin_mode = 1;
+
+adf4350_regs::adf4350_regs(adf4350* _adf4350){
+    d_adf4350 = _adf4350;
+
+    /* reg 0 */
+    d_int = uint16_t(100);
+    d_frac = 0;
+    /* reg 1 */
+    d_mod = uint16_t(0xfff);                      /* max fractional accuracy */
+    /* reg 2 */
+    d_10_bit_r_counter = uint16_t(2);
+    /* reg 3 */
+    /* reg 4 */
+    d_divider_select = 0;
+    d_8_bit_band_select_clock_divider_value = 0;
+    /* reg 5 */
+}
+
+adf4350_regs::~adf4350_regs(void){
+}
+
+uint32_t
+adf4350_regs::_reg_shift(uint32_t data, uint32_t shift){
+        return data << shift;
+    }
+
+void
+adf4350_regs::_load_register(uint8_t addr){
+       uint32_t data;
+       switch (addr){
+               case 0: data = (
+                       _reg_shift(d_int, 15)                           |
+                       _reg_shift(d_frac, 3)); break;
+               case 1: data = (
+                       _reg_shift(s_prescaler, 27)                     |
+                       _reg_shift(s_phase, 15)                         |
+                       _reg_shift(d_mod, 3)); break;
+               case 2: data = (
+                       _reg_shift(s_low_noise_and_low_spur_modes, 29)  |
+                       _reg_shift(s_muxout, 26)                        |
+                       _reg_shift(s_reference_doubler, 25)             |
+                       _reg_shift(s_rdiv2, 24)                         |
+                       _reg_shift(d_10_bit_r_counter, 14)              |
+                       _reg_shift(s_double_buff, 13)                   |
+                       _reg_shift(s_charge_pump_setting, 9)            |
+                       _reg_shift(s_ldf, 8)                            |
+                       _reg_shift(s_ldp, 7)                            |
+                       _reg_shift(s_pd_polarity, 6)                    |
+                       _reg_shift(s_power_down, 5)                     |
+                       _reg_shift(s_cp_three_state, 4)                 |
+                       _reg_shift(s_counter_reset, 3)); break;
+               case 3: data = (
+                       _reg_shift(s_csr, 18)                           |
+                       _reg_shift(s_clk_div_mode, 15)                  |
+                       _reg_shift(s_12_bit_clock_divider_value, 3)); break;
+               case 4: data = (
+                       _reg_shift(s_feedback_select, 23)               |
+                       _reg_shift(d_divider_select, 20)                |
+                       _reg_shift(d_8_bit_band_select_clock_divider_value, 12) |
+                       _reg_shift(s_vco_power_down, 11)                |
+                       _reg_shift(s_mtld, 10)                          |
+                       _reg_shift(s_aux_output_select, 9)              |
+                       _reg_shift(s_aux_output_enable, 8)              |
+                       _reg_shift(s_aux_output_power, 6)               |
+                       _reg_shift(s_rf_output_enable, 5)               |
+                       _reg_shift(s_output_power, 3)); break;
+               case 5: data = (
+                       _reg_shift(s_ld_pin_mode, 22)); break;
+               default: return;
+       }
+       /* write the data out to spi */
+       d_adf4350->_write(addr, data);
+}
diff --git a/usrp/host/lib/db_wbxng_adf4350_regs.h b/usrp/host/lib/db_wbxng_adf4350_regs.h
new file mode 100644 (file)
index 0000000..dc941ee
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2009 Ettus Research LLC
+ */
+
+#ifndef ADF4350_REGS_H
+#define ADF4350_REGS_H
+
+#include <usrp/db_base.h>
+#include <stdint.h>
+
+class adf4350;
+
+class adf4350_regs
+{
+public:
+    adf4350_regs(adf4350* _adf4350);
+    ~adf4350_regs();
+
+    adf4350* d_adf4350;
+
+    uint32_t _reg_shift(uint32_t data, uint32_t shift);
+    void _load_register(uint8_t addr);
+
+    /* reg 0 */
+    uint16_t d_int;
+    uint16_t d_frac;
+    /* reg 1 */
+    static const uint8_t s_prescaler;
+    static const uint16_t s_phase;
+    uint16_t d_mod;
+    /* reg 2 */
+    static const uint8_t s_low_noise_and_low_spur_modes;
+    static const uint8_t s_muxout;
+    static const uint8_t s_reference_doubler;
+    static const uint8_t s_rdiv2;
+    uint16_t d_10_bit_r_counter;
+    static const uint8_t s_double_buff;
+    static const uint8_t s_charge_pump_setting;
+    static const uint8_t s_ldf;
+    static const uint8_t s_ldp;
+    static const uint8_t s_pd_polarity;
+    static const uint8_t s_power_down;
+    static const uint8_t s_cp_three_state;
+    static const uint8_t s_counter_reset;
+    /* reg 3 */
+    static const uint8_t s_csr;
+    static const uint8_t s_clk_div_mode;
+    static const uint16_t s_12_bit_clock_divider_value;
+    /* reg 4 */
+    static const uint8_t s_feedback_select;
+    uint8_t d_divider_select;
+    uint8_t d_8_bit_band_select_clock_divider_value;
+    static const uint8_t s_vco_power_down;
+    static const uint8_t s_mtld;
+    static const uint8_t s_aux_output_select;
+    static const uint8_t s_aux_output_enable;
+    static const uint8_t s_aux_output_power;
+    static const uint8_t s_rf_output_enable;
+    static const uint8_t s_output_power;
+    /* reg 5 */
+    static const uint8_t s_ld_pin_mode;
+};
+
+#endif /* ADF4350_REGS_H */
index 6bad9a2987d7a619dfa9a83d115d9c3b00a1a3df..7d1e1871402043e8f446cbe5adf1f8b542f3f669 100644 (file)
@@ -1,18 +1,18 @@
 #
 # Copyright 2005,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 version 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 this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
@@ -78,6 +78,9 @@
 "WBX LO TX"            0x0050
 "WBX LO RX"            0x0051
 
+"WBX NG TX"            0x0052
+"WBX NG RX"            0x0053
+
 "XCVR2450 Tx"          0x0060
 "XCVR2450 Rx"          0x0061