Merge commit 'v3.3.0' into upstream
[debian/gnuradio] / usrp / host / include / usrp / usrp_standard.h
diff --git a/usrp/host/include/usrp/usrp_standard.h b/usrp/host/include/usrp/usrp_standard.h
new file mode 100644 (file)
index 0000000..a631f8b
--- /dev/null
@@ -0,0 +1,452 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,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 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.
+ */
+
+#ifndef INCLUDED_USRP_STANDARD_H
+#define INCLUDED_USRP_STANDARD_H
+
+#include <usrp/usrp_basic.h>
+#include <boost/shared_ptr.hpp>
+#include <usrp/usrp_tune_result.h>
+
+class usrp_standard_tx;
+class usrp_standard_rx;
+
+typedef boost::shared_ptr<usrp_standard_tx> usrp_standard_tx_sptr;
+typedef boost::shared_ptr<usrp_standard_rx> usrp_standard_rx_sptr;
+
+/*!
+ * \ingroup usrp
+ */
+class usrp_standard_common
+{
+  int  d_fpga_caps;            // capability register val
+
+protected:
+  usrp_standard_common(usrp_basic *parent);
+
+public:
+  /*!
+   *\brief does the FPGA implement the final Rx half-band filter?
+   * If it doesn't, the maximum decimation factor with proper gain 
+   * is 1/2 of what it would otherwise be.
+   */
+  bool has_rx_halfband() const;
+
+  /*!
+   * \brief number of digital downconverters implemented in the FPGA
+   * This will be 0, 1, 2 or 4.
+   */
+  int nddcs() const;
+
+  /*!
+   *\brief does the FPGA implement the initial Tx half-band filter?
+   */
+  bool has_tx_halfband() const;
+
+  /*!
+   * \brief number of digital upconverters implemented in the FPGA
+   * This will be 0, 1, or 2.
+   */
+  int nducs() const;
+
+  /*!
+   * \brief Calculate the frequency to use for setting the digital up or down converter.
+   *
+   * \param target_freq is the desired RF frequency (Hz).
+   * \param baseband_freq is the RF frequency that corresponds to DC in the IF coming from the d'board.
+   * \param  fs is the sampling frequency.
+   * \param[out] dxc_freq the frequency to program into the DDC (or DUC).
+   * \param[out] inverted is true if we're operating in an inverted Nyquist zone.
+   */
+  static void calc_dxc_freq(double target_freq, double baseband_freq, double fs,
+                           double *dxc_freq, bool *inverted);
+};
+
+/*!
+ * \brief The C++ interface the receive side of the USRP
+ * \ingroup usrp
+ *
+ * This is the recommended interface to USRP receive functionality
+ * for applications that use the USRP but not GNU Radio.
+ */
+class usrp_standard_rx : public usrp_basic_rx, public usrp_standard_common
+{
+ private:
+  static const int     MAX_CHAN = 4;
+  unsigned int         d_decim_rate;
+  int                  d_nchan;
+  int                  d_sw_mux;
+  int                  d_hw_mux;
+  double               d_rx_freq[MAX_CHAN];
+
+ protected:
+  usrp_standard_rx (int which_board,
+                   unsigned int decim_rate,
+                   int nchan = 1,
+                   int mux = -1,
+                   int mode = 0,
+                   int fusb_block_size = 0,
+                   int fusb_nblocks = 0,
+                   const std::string fpga_filename = "",
+                   const std::string firmware_filename = ""
+                   );  // throws if trouble
+
+  bool write_hw_mux_reg ();
+
+ public:
+
+  enum {
+    FPGA_MODE_NORMAL     = 0x00,
+    FPGA_MODE_LOOPBACK   = 0x01,
+    FPGA_MODE_COUNTING   = 0x02,
+    FPGA_MODE_COUNTING_32BIT   = 0x04
+  };
+
+  ~usrp_standard_rx ();
+
+  /*!
+   * \brief invokes constructor, returns shared_ptr or shared_ptr equivalent of 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param decim_rate      decimation factor
+   * \param nchan           number of channels
+   * \param mux                     Rx mux setting, \sa set_mux
+   * \param mode            mode
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   * \param fpga_filename    Name of rbf file to load
+   * \param firmware_filename Name of ihx file to load
+   */
+  static usrp_standard_rx_sptr make(int which_board,
+                                   unsigned int decim_rate,
+                                   int nchan = 1,
+                                   int mux = -1,
+                                   int mode = 0,
+                                   int fusb_block_size = 0,
+                                   int fusb_nblocks = 0,
+                                   const std::string fpga_filename = "",
+                                   const std::string firmware_filename = ""
+                                   );
+  /*!
+   * \brief Set decimator rate.  \p rate MUST BE EVEN and in [8, 256].
+   *
+   * The final complex sample rate across the USB is
+   *   adc_freq () / decim_rate () * nchannels ()
+   */
+  bool set_decim_rate  (unsigned int rate);
+
+  /*!
+   * \brief Set number of active channels.  \p nchannels must be 1, 2 or 4.
+   *
+   * The final complex sample rate across the USB is
+   *   adc_freq () / decim_rate () * nchannels ()
+   */
+  bool set_nchannels (int nchannels);
+
+  /*!
+   * \brief Set input mux configuration.
+   *
+   * This determines which ADC (or constant zero) is connected to 
+   * each DDC input.  There are 4 DDCs.  Each has two inputs.
+   *
+   * <pre>
+   * Mux value:
+   *
+   *    3                   2                   1                       
+   *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   * |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
+   * +-------+-------+-------+-------+-------+-------+-------+-------+
+   *
+   * Each 4-bit I field is either 0,1,2,3
+   * Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
+   * All Q's must be 0xf or none of them may be 0xf
+   * </pre>
+   */
+  bool set_mux  (int mux);
+
+  /*!
+   * Determine the appropriate Rx mux value as a function of the subdevice choosen
+   * and the characteristics of the respective daughterboard.
+   */
+  int determine_rx_mux_value(const usrp_subdev_spec &ss);
+  int determine_rx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b);
+
+  /*!
+   * \brief set the frequency of the digital down converter.
+   *
+   * \p channel must be in the range [0,3].  \p freq is the center
+   * frequency in Hz.  \p freq may be either negative or postive.
+   * The frequency specified is quantized.  Use rx_freq to retrieve
+   * the actual value used.
+   */
+  bool set_rx_freq (int channel, double freq);  
+
+  /*!
+   * \brief set fpga mode
+   */
+  bool set_fpga_mode (int mode);
+
+  /*!
+   * \brief Set the digital down converter phase register.
+   *
+   * \param channel    which ddc channel [0, 3]
+   * \param phase      32-bit integer phase value.
+   */
+  bool set_ddc_phase(int channel, int phase);
+
+  /*!
+   * \brief Specify Rx data format.
+   *
+   * \param format     format specifier
+   *
+   * Rx data format control register
+   *
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-----------------------------------------+-+-+---------+-------+
+   *  |          Reserved (Must be zero)        |B|Q|  WIDTH  | SHIFT |
+   *  +-----------------------------------------+-+-+---------+-------+
+   *
+   *  SHIFT specifies arithmetic right shift [0, 15]
+   *  WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid)
+   *  Q     if set deliver both I & Q, else just I
+   *  B     if set bypass half-band filter.
+   *
+   * Right now the acceptable values are:
+   *
+   *   B  Q  WIDTH  SHIFT
+   *   0  1    16     0
+   *   0  1     8     8
+   *
+   * More valid combos to come.
+   *
+   * Default value is 0x00000300  16-bits, 0 shift, deliver both I & Q.
+   */
+  bool set_format(unsigned int format);
+
+  static unsigned int make_format(int width=16, int shift=0,
+                                 bool want_q=true, bool bypass_halfband=false);
+  static int format_width(unsigned int format);
+  static int format_shift(unsigned int format);
+  static bool format_want_q(unsigned int format);
+  static bool format_bypass_halfband(unsigned int format);
+
+  /*!
+   * \brief High-level "tune" method.  Works for the single channel case.
+   *
+   * This method adjusts both the daughterboard LO and the DDC so that
+   * target_freq ends up at DC in the complex baseband samples.
+   *
+   * \param chan  which DDC channel we're controlling (almost always 0).
+   * \param db    the daughterboard we're controlling.
+   * \param target_freq the RF frequency we want at DC in the complex baseband.
+   * \param[out] result details how the hardware was configured.
+   *
+   * \returns true iff everything was successful.
+   */
+  bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result);
+  
+
+  // ACCESSORS
+  unsigned int decim_rate () const;
+  double rx_freq (int channel) const;
+  int nchannels () const;
+  int mux () const;
+  unsigned int format () const;
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+// ----------------------------------------------------------------
+
+/*!
+ * \brief The C++ interface the transmit side of the USRP
+ * \ingroup usrp
+ *
+ * This is the recommended interface to USRP transmit functionality
+ * for applications that use the USRP but not GNU Radio.
+ *
+ * Uses digital upconverter (coarse & fine modulators) in AD9862...
+ */
+class usrp_standard_tx : public usrp_basic_tx, public usrp_standard_common
+{
+ public:
+  enum coarse_mod_t {
+    CM_NEG_FDAC_OVER_4,                // -32 MHz
+    CM_NEG_FDAC_OVER_8,                // -16 MHz
+    CM_OFF,
+    CM_POS_FDAC_OVER_8,                // +16 MHz
+    CM_POS_FDAC_OVER_4         // +32 MHz
+  };
+
+ protected:
+  static const int     MAX_CHAN = 2;
+  unsigned int         d_interp_rate;
+  int                  d_nchan;
+  int                  d_sw_mux;
+  int                  d_hw_mux;
+  double               d_tx_freq[MAX_CHAN];
+  coarse_mod_t         d_coarse_mod[MAX_CHAN];
+  unsigned char                d_tx_modulator_shadow[MAX_CHAN];
+
+  virtual bool set_coarse_modulator (int channel, coarse_mod_t cm);
+  usrp_standard_tx::coarse_mod_t coarse_modulator (int channel) const;
+
+ protected:
+  usrp_standard_tx (int which_board,
+                   unsigned int interp_rate,
+                   int nchan = 1,
+                   int mux = -1,
+                   int fusb_block_size = 0,
+                   int fusb_nblocks = 0,
+                   const std::string fpga_filename = "",
+                   const std::string firmware_filename = ""
+                   );  // throws if trouble
+
+  bool write_hw_mux_reg ();
+
+ public:
+  ~usrp_standard_tx ();
+
+  /*!
+   * \brief invokes constructor, returns shared_ptr or shared_ptr equivalent of 0 if trouble
+   *
+   * \param which_board             Which USRP board on usb (not particularly useful; use 0)
+   * \param interp_rate             interpolation factor
+   * \param nchan           number of channels
+   * \param mux                     Tx mux setting, \sa set_mux
+   * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
+   *                         Use zero for a reasonable default.
+   * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
+   * \param fpga_filename    Name of rbf file to load
+   * \param firmware_filename Name of ihx file to load
+   */
+  static usrp_standard_tx_sptr make(int which_board,
+                                   unsigned int interp_rate,
+                                   int nchan = 1,
+                                   int mux = -1,
+                                   int fusb_block_size = 0,
+                                   int fusb_nblocks = 0,
+                                   const std::string fpga_filename = "",
+                                   const std::string firmware_filename = ""
+                                   );
+
+  /*!
+   * \brief Set interpolator rate.  \p rate must be in [4, 512] and a multiple of 4.
+   *
+   * The final complex sample rate across the USB is
+   *   dac_freq () / interp_rate () * nchannels ()
+   */
+  virtual bool set_interp_rate (unsigned int rate);
+
+  /*!
+   * \brief Set number of active channels.  \p nchannels must be 1 or 2.
+   *
+   * The final complex sample rate across the USB is
+   *   dac_freq () / decim_rate () * nchannels ()
+   */
+  bool set_nchannels  (int nchannels);
+
+  /*!
+   * \brief Set output mux configuration.
+   *
+   * <pre>
+   *     3                   2                   1                       
+   *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+   *  +-------------------------------+-------+-------+-------+-------+
+   *  |                               | DAC3  | DAC2  | DAC1  |  DAC0 |
+   *  +-------------------------------+-------+-------+-------+-------+
+   * 
+   *  There are two interpolators with complex inputs and outputs.
+   *  There are four DACs.
+   * 
+   *  Each 4-bit DACx field specifies the source for the DAC and
+   *  whether or not that DAC is enabled.  Each subfield is coded
+   *  like this: 
+   * 
+   *     3 2 1 0
+   *    +-+-----+
+   *    |E|  N  |
+   *    +-+-----+
+   * 
+   *  Where E is set if the DAC is enabled, and N specifies which
+   *  interpolator output is connected to this DAC.
+   * 
+   *   N   which interp output
+   *  ---  -------------------
+   *   0   chan 0 I
+   *   1   chan 0 Q
+   *   2   chan 1 I
+   *   3   chan 1 Q
+   * </pre>
+   */
+  bool set_mux  (int mux);
+
+  /*!
+   * Determine the appropriate Tx mux value as a function of the subdevice choosen
+   * and the characteristics of the respective daughterboard.
+   */
+  int determine_tx_mux_value(const usrp_subdev_spec &ss);
+  int determine_tx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b);
+
+  /*!
+   * \brief set the frequency of the digital up converter.
+   *
+   * \p channel must be in the range [0,1].  \p freq is the center
+   * frequency in Hz.  It must be in the range [-44M, 44M].
+   * The frequency specified is quantized.  Use tx_freq to retrieve
+   * the actual value used.
+   */
+  virtual bool set_tx_freq (int channel, double freq);  // chan: [0,1]
+
+  // ACCESSORS
+  unsigned int interp_rate () const;
+  double tx_freq (int channel) const;
+  int nchannels () const;
+  int mux () const;
+
+  /*!
+   * \brief High-level "tune" method.  Works for the single channel case.
+   *
+   * This method adjusts both the daughterboard LO and the DUC so that
+   * DC in the complex baseband samples ends up at RF target_freq.
+   *
+   * \param chan  which DUC channel we're controlling (usually == which_side).
+   * \param db    the daughterboard we're controlling.
+   * \param target_freq the RF frequency we want our baseband translated to.
+   * \param[out] result details how the hardware was configured.
+   *
+   * \returns true iff everything was successful.
+   */
+  bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result);
+
+
+  // called in base class to derived class order
+  bool start ();
+  bool stop ();
+};
+
+#endif /* INCLUDED_USRP_STANDARD_H */