GNU Radio 3.4.2 C++ API
usrp_standard.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2004,2008,2009 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef INCLUDED_USRP_STANDARD_H
00024 #define INCLUDED_USRP_STANDARD_H
00025 
00026 #include <usrp/usrp_basic.h>
00027 #include <boost/shared_ptr.hpp>
00028 #include <usrp/usrp_tune_result.h>
00029 
00030 class usrp_standard_tx;
00031 class usrp_standard_rx;
00032 
00033 typedef boost::shared_ptr<usrp_standard_tx> usrp_standard_tx_sptr;
00034 typedef boost::shared_ptr<usrp_standard_rx> usrp_standard_rx_sptr;
00035 
00036 /*!
00037  * \ingroup usrp
00038  */
00039 class usrp_standard_common
00040 {
00041   int   d_fpga_caps;            // capability register val
00042 
00043 protected:
00044   usrp_standard_common(usrp_basic *parent);
00045 
00046 public:
00047   /*!
00048    *\brief does the FPGA implement the final Rx half-band filter?
00049    * If it doesn't, the maximum decimation factor with proper gain 
00050    * is 1/2 of what it would otherwise be.
00051    */
00052   bool has_rx_halfband() const;
00053 
00054   /*!
00055    * \brief number of digital downconverters implemented in the FPGA
00056    * This will be 0, 1, 2 or 4.
00057    */
00058   int nddcs() const;
00059 
00060   /*!
00061    *\brief does the FPGA implement the initial Tx half-band filter?
00062    */
00063   bool has_tx_halfband() const;
00064 
00065   /*!
00066    * \brief number of digital upconverters implemented in the FPGA
00067    * This will be 0, 1, or 2.
00068    */
00069   int nducs() const;
00070 
00071   /*!
00072    * \brief Calculate the frequency to use for setting the digital up or down converter.
00073    *
00074    * \param target_freq is the desired RF frequency (Hz).
00075    * \param baseband_freq is the RF frequency that corresponds to DC in the IF coming from the d'board.
00076    * \param  fs is the sampling frequency.
00077    * \param[out] dxc_freq the frequency to program into the DDC (or DUC).
00078    * \param[out] inverted is true if we're operating in an inverted Nyquist zone.
00079    */
00080   static void calc_dxc_freq(double target_freq, double baseband_freq, double fs,
00081                             double *dxc_freq, bool *inverted);
00082 };
00083 
00084 /*!
00085  * \brief The C++ interface the receive side of the USRP
00086  * \ingroup usrp
00087  *
00088  * This is the recommended interface to USRP receive functionality
00089  * for applications that use the USRP but not GNU Radio.
00090  */
00091 class usrp_standard_rx : public usrp_basic_rx, public usrp_standard_common
00092 {
00093  private:
00094   static const int      MAX_CHAN = 4;
00095   unsigned int          d_decim_rate;
00096   int                   d_nchan;
00097   int                   d_sw_mux;
00098   int                   d_hw_mux;
00099   double                d_rx_freq[MAX_CHAN];
00100 
00101  protected:
00102   usrp_standard_rx (int which_board,
00103                     unsigned int decim_rate,
00104                     int nchan = 1,
00105                     int mux = -1,
00106                     int mode = 0,
00107                     int fusb_block_size = 0,
00108                     int fusb_nblocks = 0,
00109                     const std::string fpga_filename = "",
00110                     const std::string firmware_filename = ""
00111                     );  // throws if trouble
00112 
00113   bool write_hw_mux_reg ();
00114 
00115  public:
00116 
00117   enum {
00118     FPGA_MODE_NORMAL     = 0x00,
00119     FPGA_MODE_LOOPBACK   = 0x01,
00120     FPGA_MODE_COUNTING   = 0x02,
00121     FPGA_MODE_COUNTING_32BIT   = 0x04
00122   };
00123 
00124   ~usrp_standard_rx ();
00125 
00126   /*!
00127    * \brief invokes constructor, returns shared_ptr or shared_ptr equivalent of 0 if trouble
00128    *
00129    * \param which_board      Which USRP board on usb (not particularly useful; use 0)
00130    * \param decim_rate       decimation factor
00131    * \param nchan            number of channels
00132    * \param mux              Rx mux setting, \sa set_mux
00133    * \param mode             mode
00134    * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
00135    *                         Use zero for a reasonable default.
00136    * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
00137    * \param fpga_filename    Name of rbf file to load
00138    * \param firmware_filename Name of ihx file to load
00139    */
00140   static usrp_standard_rx_sptr make(int which_board,
00141                                     unsigned int decim_rate,
00142                                     int nchan = 1,
00143                                     int mux = -1,
00144                                     int mode = 0,
00145                                     int fusb_block_size = 0,
00146                                     int fusb_nblocks = 0,
00147                                     const std::string fpga_filename = "",
00148                                     const std::string firmware_filename = ""
00149                                     );
00150   /*!
00151    * \brief Set decimator rate.  \p rate MUST BE EVEN and in [8, 256].
00152    *
00153    * The final complex sample rate across the USB is
00154    *   adc_freq () / decim_rate () * nchannels ()
00155    */
00156   bool set_decim_rate  (unsigned int rate);
00157 
00158   /*!
00159    * \brief Set number of active channels.  \p nchannels must be 1, 2 or 4.
00160    *
00161    * The final complex sample rate across the USB is
00162    *   adc_freq () / decim_rate () * nchannels ()
00163    */
00164   bool set_nchannels (int nchannels);
00165 
00166   /*!
00167    * \brief Set input mux configuration.
00168    *
00169    * This determines which ADC (or constant zero) is connected to 
00170    * each DDC input.  There are 4 DDCs.  Each has two inputs.
00171    *
00172    * <pre>
00173    * Mux value:
00174    *
00175    *    3                   2                   1                       
00176    *  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
00177    * +-------+-------+-------+-------+-------+-------+-------+-------+
00178    * |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
00179    * +-------+-------+-------+-------+-------+-------+-------+-------+
00180    *
00181    * Each 4-bit I field is either 0,1,2,3
00182    * Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
00183    * All Q's must be 0xf or none of them may be 0xf
00184    * </pre>
00185    */
00186   bool set_mux  (int mux);
00187 
00188   /*!
00189    * Determine the appropriate Rx mux value as a function of the subdevice choosen
00190    * and the characteristics of the respective daughterboard.
00191    */
00192   int determine_rx_mux_value(const usrp_subdev_spec &ss);
00193   int determine_rx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b);
00194 
00195   /*!
00196    * \brief set the frequency of the digital down converter.
00197    *
00198    * \p channel must be in the range [0,3].  \p freq is the center
00199    * frequency in Hz.  \p freq may be either negative or postive.
00200    * The frequency specified is quantized.  Use rx_freq to retrieve
00201    * the actual value used.
00202    */
00203   bool set_rx_freq (int channel, double freq);  
00204 
00205   /*!
00206    * \brief set fpga mode
00207    */
00208   bool set_fpga_mode (int mode);
00209 
00210   /*!
00211    * \brief Set the digital down converter phase register.
00212    *
00213    * \param channel     which ddc channel [0, 3]
00214    * \param phase       32-bit integer phase value.
00215    */
00216   bool set_ddc_phase(int channel, int phase);
00217 
00218   /*!
00219    * \brief Specify Rx data format.
00220    *
00221    * \param format      format specifier
00222    *
00223    * Rx data format control register
00224    *
00225    *     3                   2                   1                       
00226    *   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
00227    *  +-----------------------------------------+-+-+---------+-------+
00228    *  |          Reserved (Must be zero)        |B|Q|  WIDTH  | SHIFT |
00229    *  +-----------------------------------------+-+-+---------+-------+
00230    *
00231    *  SHIFT specifies arithmetic right shift [0, 15]
00232    *  WIDTH specifies bit-width of I & Q samples across the USB [1, 16] (not all valid)
00233    *  Q     if set deliver both I & Q, else just I
00234    *  B     if set bypass half-band filter.
00235    *
00236    * Right now the acceptable values are:
00237    *
00238    *   B  Q  WIDTH  SHIFT
00239    *   0  1    16     0
00240    *   0  1     8     8
00241    *
00242    * More valid combos to come.
00243    *
00244    * Default value is 0x00000300  16-bits, 0 shift, deliver both I & Q.
00245    */
00246   bool set_format(unsigned int format);
00247 
00248   static unsigned int make_format(int width=16, int shift=0,
00249                                   bool want_q=true, bool bypass_halfband=false);
00250   static int format_width(unsigned int format);
00251   static int format_shift(unsigned int format);
00252   static bool format_want_q(unsigned int format);
00253   static bool format_bypass_halfband(unsigned int format);
00254 
00255   /*!
00256    * \brief High-level "tune" method.  Works for the single channel case.
00257    *
00258    * This method adjusts both the daughterboard LO and the DDC so that
00259    * target_freq ends up at DC in the complex baseband samples.
00260    *
00261    * \param chan  which DDC channel we're controlling (almost always 0).
00262    * \param db    the daughterboard we're controlling.
00263    * \param target_freq the RF frequency we want at DC in the complex baseband.
00264    * \param[out] result details how the hardware was configured.
00265    *
00266    * \returns true iff everything was successful.
00267    */
00268   bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result);
00269   
00270 
00271   // ACCESSORS
00272   unsigned int decim_rate () const;
00273   double rx_freq (int channel) const;
00274   int nchannels () const;
00275   int mux () const;
00276   unsigned int format () const;
00277 
00278   // called in base class to derived class order
00279   bool start ();
00280   bool stop ();
00281 };
00282 
00283 // ----------------------------------------------------------------
00284 
00285 /*!
00286  * \brief The C++ interface the transmit side of the USRP
00287  * \ingroup usrp
00288  *
00289  * This is the recommended interface to USRP transmit functionality
00290  * for applications that use the USRP but not GNU Radio.
00291  *
00292  * Uses digital upconverter (coarse & fine modulators) in AD9862...
00293  */
00294 class usrp_standard_tx : public usrp_basic_tx, public usrp_standard_common
00295 {
00296  public:
00297   enum coarse_mod_t {
00298     CM_NEG_FDAC_OVER_4,         // -32 MHz
00299     CM_NEG_FDAC_OVER_8,         // -16 MHz
00300     CM_OFF,
00301     CM_POS_FDAC_OVER_8,         // +16 MHz
00302     CM_POS_FDAC_OVER_4          // +32 MHz
00303   };
00304 
00305  protected:
00306   static const int      MAX_CHAN = 2;
00307   unsigned int          d_interp_rate;
00308   int                   d_nchan;
00309   int                   d_sw_mux;
00310   int                   d_hw_mux;
00311   double                d_tx_freq[MAX_CHAN];
00312   coarse_mod_t          d_coarse_mod[MAX_CHAN];
00313   unsigned char         d_tx_modulator_shadow[MAX_CHAN];
00314 
00315   virtual bool set_coarse_modulator (int channel, coarse_mod_t cm);
00316   usrp_standard_tx::coarse_mod_t coarse_modulator (int channel) const;
00317 
00318  protected:
00319   usrp_standard_tx (int which_board,
00320                     unsigned int interp_rate,
00321                     int nchan = 1,
00322                     int mux = -1,
00323                     int fusb_block_size = 0,
00324                     int fusb_nblocks = 0,
00325                     const std::string fpga_filename = "",
00326                     const std::string firmware_filename = ""
00327                     );  // throws if trouble
00328 
00329   bool write_hw_mux_reg ();
00330 
00331  public:
00332   ~usrp_standard_tx ();
00333 
00334   /*!
00335    * \brief invokes constructor, returns shared_ptr or shared_ptr equivalent of 0 if trouble
00336    *
00337    * \param which_board      Which USRP board on usb (not particularly useful; use 0)
00338    * \param interp_rate      interpolation factor
00339    * \param nchan            number of channels
00340    * \param mux              Tx mux setting, \sa set_mux
00341    * \param fusb_block_size  fast usb xfer block size.  Must be a multiple of 512. 
00342    *                         Use zero for a reasonable default.
00343    * \param fusb_nblocks     number of fast usb URBs to allocate.  Use zero for a reasonable default. 
00344    * \param fpga_filename    Name of rbf file to load
00345    * \param firmware_filename Name of ihx file to load
00346    */
00347   static usrp_standard_tx_sptr make(int which_board,
00348                                     unsigned int interp_rate,
00349                                     int nchan = 1,
00350                                     int mux = -1,
00351                                     int fusb_block_size = 0,
00352                                     int fusb_nblocks = 0,
00353                                     const std::string fpga_filename = "",
00354                                     const std::string firmware_filename = ""
00355                                     );
00356 
00357   /*!
00358    * \brief Set interpolator rate.  \p rate must be in [4, 512] and a multiple of 4.
00359    *
00360    * The final complex sample rate across the USB is
00361    *   dac_freq () / interp_rate () * nchannels ()
00362    */
00363   virtual bool set_interp_rate (unsigned int rate);
00364 
00365   /*!
00366    * \brief Set number of active channels.  \p nchannels must be 1 or 2.
00367    *
00368    * The final complex sample rate across the USB is
00369    *   dac_freq () / decim_rate () * nchannels ()
00370    */
00371   bool set_nchannels  (int nchannels);
00372 
00373   /*!
00374    * \brief Set output mux configuration.
00375    *
00376    * <pre>
00377    *     3                   2                   1                       
00378    *   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
00379    *  +-------------------------------+-------+-------+-------+-------+
00380    *  |                               | DAC3  | DAC2  | DAC1  |  DAC0 |
00381    *  +-------------------------------+-------+-------+-------+-------+
00382    * 
00383    *  There are two interpolators with complex inputs and outputs.
00384    *  There are four DACs.
00385    * 
00386    *  Each 4-bit DACx field specifies the source for the DAC and
00387    *  whether or not that DAC is enabled.  Each subfield is coded
00388    *  like this: 
00389    * 
00390    *     3 2 1 0
00391    *    +-+-----+
00392    *    |E|  N  |
00393    *    +-+-----+
00394    * 
00395    *  Where E is set if the DAC is enabled, and N specifies which
00396    *  interpolator output is connected to this DAC.
00397    * 
00398    *   N   which interp output
00399    *  ---  -------------------
00400    *   0   chan 0 I
00401    *   1   chan 0 Q
00402    *   2   chan 1 I
00403    *   3   chan 1 Q
00404    * </pre>
00405    */
00406   bool set_mux  (int mux);
00407 
00408   /*!
00409    * Determine the appropriate Tx mux value as a function of the subdevice choosen
00410    * and the characteristics of the respective daughterboard.
00411    */
00412   int determine_tx_mux_value(const usrp_subdev_spec &ss);
00413   int determine_tx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b);
00414 
00415   /*!
00416    * \brief set the frequency of the digital up converter.
00417    *
00418    * \p channel must be in the range [0,1].  \p freq is the center
00419    * frequency in Hz.  It must be in the range [-44M, 44M].
00420    * The frequency specified is quantized.  Use tx_freq to retrieve
00421    * the actual value used.
00422    */
00423   virtual bool set_tx_freq (int channel, double freq);  // chan: [0,1]
00424 
00425   // ACCESSORS
00426   unsigned int interp_rate () const;
00427   double tx_freq (int channel) const;
00428   int nchannels () const;
00429   int mux () const;
00430 
00431   /*!
00432    * \brief High-level "tune" method.  Works for the single channel case.
00433    *
00434    * This method adjusts both the daughterboard LO and the DUC so that
00435    * DC in the complex baseband samples ends up at RF target_freq.
00436    *
00437    * \param chan  which DUC channel we're controlling (usually == which_side).
00438    * \param db    the daughterboard we're controlling.
00439    * \param target_freq the RF frequency we want our baseband translated to.
00440    * \param[out] result details how the hardware was configured.
00441    *
00442    * \returns true iff everything was successful.
00443    */
00444   bool tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result);
00445 
00446 
00447   // called in base class to derived class order
00448   bool start ();
00449   bool stop ();
00450 };
00451 
00452 #endif /* INCLUDED_USRP_STANDARD_H */