/*
 * Copyright 2004 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 2, 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <string>

///////////// stuff added by Michael Perrott /////

int max_for_usrp(int in1, int in2);
double max_for_usrp(double in1, double in2);
int min_for_usrp(int in1, int in2);
double min_for_usrp(double in1, double in2);

//////////////////////////////////////////////

void mysleep(int ms);

//////////// usrp_dbid.h //////////////

#define NELEM(x) (sizeof (x) / sizeof (x[0]))

// Machine generated by gen_usrp_dbid.py from usrp_dbid.dat
//
// USRP Daughterboard ID's
//


#define USRP_DBID_BASIC_TX        0x0000
#define USRP_DBID_BASIC_RX        0x0001
#define USRP_DBID_DBS_RX          0x0002
#define USRP_DBID_TV_RX           0x0003
#define USRP_DBID_FLEX_400_RX     0x0004
#define USRP_DBID_FLEX_900_RX     0x0005
#define USRP_DBID_FLEX_1200_RX    0x0006
#define USRP_DBID_FLEX_2400_RX    0x0007
#define USRP_DBID_FLEX_400_TX     0x0008
#define USRP_DBID_FLEX_900_TX     0x0009
#define USRP_DBID_FLEX_1200_TX    0x000a
#define USRP_DBID_FLEX_2400_TX    0x000b
#define USRP_DBID_TV_RX_REV_2     0x000c
#define USRP_DBID_DBS_RX_REV_2_1  0x000d
#define USRP_DBID_LF_TX           0x000e
#define USRP_DBID_LF_RX           0x000f
#define USRP_DBID_FLEX_400_RX_MIMO_A 0x0014
#define USRP_DBID_FLEX_900_RX_MIMO_A 0x0015
#define USRP_DBID_FLEX_1200_RX_MIMO_A 0x0016
#define USRP_DBID_FLEX_2400_RX_MIMO_A 0x0017
#define USRP_DBID_FLEX_400_TX_MIMO_A 0x0018
#define USRP_DBID_FLEX_900_TX_MIMO_A 0x0019
#define USRP_DBID_FLEX_1200_TX_MIMO_A 0x001a
#define USRP_DBID_FLEX_2400_TX_MIMO_A 0x001b
#define USRP_DBID_FLEX_400_RX_MIMO_B 0x0024
#define USRP_DBID_FLEX_900_RX_MIMO_B 0x0025
#define USRP_DBID_FLEX_1200_RX_MIMO_B 0x0026
#define USRP_DBID_FLEX_2400_RX_MIMO_B 0x0027
#define USRP_DBID_FLEX_400_TX_MIMO_B 0x0028
#define USRP_DBID_FLEX_900_TX_MIMO_B 0x0029
#define USRP_DBID_FLEX_1200_TX_MIMO_B 0x002a
#define USRP_DBID_FLEX_2400_TX_MIMO_B 0x002b
#define USRP_DBID_FLEX_1800_RX    0x0030
#define USRP_DBID_FLEX_1800_TX    0x0031
#define USRP_DBID_FLEX_1800_RX_MIMO_A 0x0032
#define USRP_DBID_FLEX_1800_TX_MIMO_A 0x0033
#define USRP_DBID_FLEX_1800_RX_MIMO_B 0x0034
#define USRP_DBID_FLEX_1800_TX_MIMO_B 0x0035
#define USRP_DBID_TV_RX_REV_3     0x0040
#define USRP_DBID_EXPERIMENTAL_TX 0xfffe
#define USRP_DBID_EXPERIMENTAL_RX 0xffff

//////////// usrp_slots.h ///////////////

// daughterboard slot numbers used in some calls

static const int SLOT_TX_A = 0;
static const int SLOT_RX_A = 1;
static const int SLOT_TX_B = 2;
static const int SLOT_RX_B = 3;

//////////// usrp_prims.h ///////////////

/*
 * Low level primitives for directly messing with USRP hardware.
 *
 * If you're trying to use the USRP, you'll probably want to take a look
 * at the usrp_rx and usrp_tx classes.  They hide a bunch of low level details
 * and provide high performance streaming i/o.
 *
 * This interface is built on top of libusb, which allegedly works under
 * Linux, *BSD and Mac OS/X.  http://libusb.sourceforge.net
 */

static const int USRP_HASH_SIZE = 16;

enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED };

struct usb_dev_handle;
struct usb_device;

/*!
 * \brief initialize libusb; probe busses and devices.
 * Safe to call more than once.
 */
void usrp_one_time_init ();

/*
 * force a rescan of the buses and devices
 */
void usrp_rescan ();

/*!
 * \brief locate Nth (zero based) USRP device in system.
 * Return pointer or 0 if not found.
 *
 * The following kinds of devices are considered USRPs:
 *
 *   unconfigured USRP (no firwmare loaded)
 *   configured USRP (firmware loaded)
 *   unconfigured Cypress FX2 (only if fx2_ok_p is true)
 */
struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false);

bool usrp_usrp_p (struct usb_device *q);		//< is this a USRP
bool usrp_usrp0_p (struct usb_device *q);		//< is this a USRP Rev 0
bool usrp_usrp1_p (struct usb_device *q);		//< is this a USRP Rev 1
bool usrp_usrp2_p (struct usb_device *q);		//< is this a USRP Rev 2
bool usrp_fx2_p (struct usb_device *q);			//< is this an unconfigured Cypress FX2

bool usrp_unconfigured_usrp_p (struct usb_device *q);	//< some kind of unconfigured USRP
bool usrp_configured_usrp_p (struct usb_device *q);	//< some kind of configured USRP

/*!
 * \brief given a usb_device return an instance of the appropriate usb_dev_handle
 *
 * These routines claim the specified interface and select the
 * correct alternate interface.  (USB nomenclature is totally screwed!)
 *
 * If interface can't be opened, or is already claimed by some other
 * process, 0 is returned.
 */
struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev);
struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev);
struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev);

/*!
 * \brief close interface.
 */
bool usrp_close_cmd_interface (struct usb_dev_handle *udh);

/*!
 * \brief load intel hex format file into USRP/Cypress FX2 (8051).
 *
 * The filename extension is typically *.ihx
 *
 * Note that loading firmware may cause the device to renumerate.  I.e.,
 * change its configuration, invalidating the current device handle.
 */

usrp_load_status_t 
usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force);

/*!
 * \brief load intel hex format file into USRP FX2 (8051).
 *
 * The filename extension is typically *.ihx
 *
 * Note that loading firmware may cause the device to renumerate.  I.e.,
 * change its configuration, invalidating the current device handle.
 * If the result is ULS_OK, usrp_load_firmware_nth delays 1 second
 * then rescans the busses and devices.
 */
usrp_load_status_t
usrp_load_firmware_nth (int nth, const char *filename, bool force);

/*!
 * \brief load fpga configuration bitstream
 */
usrp_load_status_t
usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force);

/*!
 * \brief load the regular firmware and fpga bitstream in the Nth USRP.
 *
 * This is the normal starting point...
 */
bool usrp_load_standard_bits (int nth, bool force);

/*!
 * \brief copy the given \p hash into the USRP hash slot \p which.
 * The usrp implements two hash slots, 0 and 1.
 */
bool usrp_set_hash (struct usb_dev_handle *udh, int which,
		    const unsigned char hash[USRP_HASH_SIZE]);

/*!
 * \brief retrieve the \p hash from the USRP hash slot \p which.
 * The usrp implements two hash slots, 0 and 1.
 */
bool usrp_get_hash (struct usb_dev_handle *udh, int which,
		    unsigned char hash[USRP_HASH_SIZE]);

bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value);
bool usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value);
bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on);
bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on);
bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on);
bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on);
bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on);
bool usrp_set_sleep_bits (struct usb_dev_handle *udh, int bits, int mask);
bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on);

bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p);
bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p);

// i2c_read and i2c_write are limited to a maximum len of 64 bytes.

bool usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr,
		     const void *buf, int len);

bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr,
		    void *buf, int len);

// spi_read and spi_write are limited to a maximum of 64 bytes
// See usrp_spi_defs.h for more info

bool usrp_spi_write (struct usb_dev_handle *udh,
		     int optional_header, int enables, int format,
		     const void *buf, int len);

bool usrp_spi_read (struct usb_dev_handle *udh,
		     int optional_header, int enables, int format,
		     void *buf, int len);


bool usrp_9862_write (struct usb_dev_handle *udh,
		      int which_codec,			// [0,  1]
		      int regno,			// [0, 63]
		      int value);			// [0, 255]	

bool usrp_9862_read (struct usb_dev_handle *udh,
		     int which_codec,			// [0,  1]
		     int regno,				// [0, 63]
		     unsigned char *value);		// [0, 255]

/*!
 * \brief Write multiple 9862 regs at once.
 *
 * \p buf contains alternating register_number, register_value pairs.
 * \p len must be even and is the length of buf in bytes.
 */
bool usrp_9862_write_many (struct usb_dev_handle *udh, int which_codec,
			   const unsigned char *buf, int len);
			   

/*!
 * \brief write specified regs to all 9862's in the system
 */
bool usrp_9862_write_many_all (struct usb_dev_handle *udh,
			       const unsigned char *buf, int len);
			   

// Write 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
// Which EEPROM is determined by i2c_addr.  See i2c_addr.h

bool usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr,
			int eeprom_offset, const void *buf, int len);


// Read 24LC024 / 24LC025 EEPROM on motherboard or daughterboard.
// Which EEPROM is determined by i2c_addr.  See i2c_addr.h

bool usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr,
		       int eeprom_offset, void *buf, int len);


// Slot specific i/o routines

/*!
 * \brief write to the specified aux dac.
 *
 * \p slot: which Tx or Rx slot to write.
 *    N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's
 *          SLOT_TX_B and SLOT_RX_B share the same AUX DAC's
 *
 * \p which_dac: [0,3]  RX slots must use only 0 and 1.
 *			TX slots must use only 2 and 3.
 *
 * AUX DAC 3 is really the 9862 sigma delta output.
 *
 * \p value to write to aux dac.  All dacs take straight
 * binary values.  Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit,
 * the interface is in terms of 12-bit values [0,4095]
 */
bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot,
			 int which_dac, int value);

/*!
 * \brief Read the specified aux adc
 *
 * \p slot: which Tx or Rx slot to read aux dac
 * \p which_adc: [0,1]  which of the two adcs to read
 * \p *value: return value, 12-bit straight binary.
 */
bool usrp_read_aux_adc (struct usb_dev_handle *udh, int slot,
			int which_adc, int *value);


/*!
 * \brief usrp daughterboard id to name mapping
 */
const std::string usrp_dbid_to_string (int dbid);


enum usrp_dbeeprom_status_t { UDBE_OK, UDBE_BAD_SLOT, UDBE_NO_EEPROM, UDBE_INVALID_EEPROM };

struct usrp_dboard_eeprom {
  unsigned short	id;		// d'board identifier code
  unsigned short	oe;		// fpga output enables:
					//   If bit set, i/o pin is an output from FPGA.
  short			offset[2];	// ADC/DAC offset correction
};

/*!
 * \brief Read and return parsed daughterboard eeprom
 */
usrp_dbeeprom_status_t
usrp_read_dboard_eeprom (struct usb_dev_handle *udh,
			 int slot_id, usrp_dboard_eeprom *eeprom);

/*!
 * \brief write ADC/DAC offset calibration constants to d'board eeprom
 */
bool usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id,
				short offset0, short offset1);


//////////// usrp_basic.h ///////////////

/*
 * ----------------------------------------------------------------------
 * Mid level interface to the Universal Software Radio Peripheral (Rev 1)
 *
 * These classes implement the basic functionality for talking to the
 * USRP.  They try to be as independent of the signal processing code
 * in FPGA as possible.  They implement access to the low level
 * peripherals on the board, provide a common way for reading and
 * writing registers in the FPGA, and provide the high speed interface
 * to streaming data across the USB.
 *
 * It is expected that subclasses will be derived that provide
 * access to the functionality to a particular FPGA configuration.
 * ----------------------------------------------------------------------
 */

#define MAX_REGS 128
//! magic value used on alternate register read interfaces
#define READ_FAILED 99999
#define MAX_CHAN_RX 4
#define MAX_CHAN_TX 2

struct usb_dev_handle;
class  fusb_devhandle;
class  fusb_ephandle;

/*!
 * \brief base class for usrp operations
 */
class usrp_basic
{
private:
  // NOT IMPLEMENTED
  usrp_basic (const usrp_basic &rhs);			// no copy constructor
  usrp_basic &operator= (const usrp_basic &rhs);	// no assignment operator

public:
  struct usb_dev_handle	*d_udh;
protected:
  int			 d_usb_data_rate;	// bytes/sec
  int			 d_bytes_per_poll;	// how often to poll for overruns
  bool			 d_verbose;

  unsigned int		 d_fpga_shadows[MAX_REGS];

  usrp_basic (int which_board,
	      struct usb_dev_handle *open_interface (struct usb_device *dev));

  /*!
   * \brief advise usrp_basic of usb data rate (bytes/sec)
   *
   * N.B., this doesn't tweak any hardware.  Derived classes
   * should call this to inform us of the data rate whenever it's
   * first set or if it changes.
   *
   * \param usb_data_rate	bytes/sec
   */
  void set_usb_data_rate (int usb_data_rate);
  
  /*!
   * \brief Write auxiliary digital to analog converter.
   *
   * \param slot	Which Tx or Rx slot to write.
   *    		N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
   *          		SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
   * \param which_dac	[0,3] RX slots must use only 0 and 1.  TX slots must use only 2 and 3.
   * \param value	[0,4095]
   * \returns true iff successful
   */
  bool write_aux_dac (int slot, int which_dac, int value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param slot	2-bit slot number. E.g., SLOT_TX_A
   * \param which_adc	[0,1]
   * \param value	return 12-bit value [0,4095]
   * \returns true iff successful
   */
  bool read_aux_adc (int slot, int which_adc, int *value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param slot	2-bit slot number. E.g., SLOT_TX_A
   * \param which_adc	[0,1]
   * \returns value in the range [0,4095] if successful, else READ_FAILED.
   */
  int read_aux_adc (int slot, int which_adc);

public:
  virtual ~usrp_basic ();

  /*!
   * \brief return frequency of master oscillator on USRP
   */
  long  fpga_master_clock_freq () const { return 64000000; }

  /*!
   * \returns usb data rate in bytes/sec
   */
  int usb_data_rate () const { return d_usb_data_rate; }

  void set_verbose (bool on) { d_verbose = on; }


  /*!
   * \brief Write EEPROM on motherboard or any daughterboard.
   * \param i2c_addr		I2C bus address of EEPROM
   * \param eeprom_offset	byte offset in EEPROM to begin writing
   * \param buf			the data to write
   * \returns true iff sucessful
   */
  bool write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf);

  /*!
   * \brief Read EEPROM on motherboard or any daughterboard.
   * \param i2c_addr		I2C bus address of EEPROM
   * \param eeprom_offset	byte offset in EEPROM to begin reading
   * \param len			number of bytes to read
   * \param str_out             resulting string - must have length > len
   * \returns the data read if successful, else a zero length string.
   */
  void read_eeprom (int i2c_addr, int eeprom_offset, int len, char *str_out);

  /*!
   * \brief Write to I2C peripheral
   * \param i2c_addr		I2C bus address (7-bits)
   * \param buf			the data to write
   * \returns true iff successful
   * Writes are limited to a maximum of of 64 bytes.
   */
  bool write_i2c (int i2c_addr, const std::string buf);

  /*!
   * \brief Read from I2C peripheral
   * \param i2c_addr		I2C bus address (7-bits)
   * \param len			number of bytes to read
   * \param str_out             resulting string - must have length > len
   * \returns the data read if successful, else a zero length string.
   * Reads are limited to a maximum of 64 bytes.
   */
  void read_i2c (int i2c_addr, int len, char *str_out);

  /*!
   * \brief Set ADC offset correction
   * \param which	which ADC[0,3]: 0 = RX_A I, 1 = RX_A Q...
   * \param offset	16-bit value to subtract from raw ADC input.
   */
  bool set_adc_offset (int which, int offset);

  /*!
   * \brief Set DAC offset correction
   * \param which	which DAC[0,3]: 0 = TX_A I, 1 = TX_A Q...
   * \param offset	10-bit offset value (ambiguous format:  See AD9862 datasheet).
   * \param offset_pin	1-bit value.  If 0 offset applied to -ve differential pin;
   *                                  If 1 offset applied to +ve differential pin.
   */
  bool set_dac_offset (int which, int offset, int offset_pin);

  /*!
   * \brief Control ADC input buffer
   * \param which 	which ADC[0,3]
   * \param bypass	if non-zero, bypass input buffer and connect input
   *	                directly to switched cap SHA input of RxPGA.
   */
  bool set_adc_buffer_bypass (int which, bool bypass);


  // ----------------------------------------------------------------
  // Low level implementation routines.
  // You probably shouldn't be using these...
  //

  bool _set_led (int which, bool on);

  /*!
   * \brief Write FPGA register.
   * \param regno	7-bit register number
   * \param value	32-bit value
   * \returns true iff successful
   */
  bool _write_fpga_reg (int regno, int value);	//< 7-bit regno, 32-bit value

  /*!
   * \brief Read FPGA register.
   * \param regno	7-bit register number
   * \param value	32-bit value
   * \returns true iff successful
   */
  bool _read_fpga_reg (int regno, int *value);	//< 7-bit regno, 32-bit value

  /*!
   * \brief Read FPGA register.
   * \param regno	7-bit register number
   * \returns register value if successful, else READ_FAILED
   */
  int  _read_fpga_reg (int regno);

  /*!
   * \brief Write AD9862 register.
   * \param which_codec 0 or 1
   * \param regno	6-bit register number
   * \param value	8-bit value
   * \returns true iff successful
   */
  bool _write_9862 (int which_codec, int regno, unsigned char value);

  /*!
   * \brief Read AD9862 register.
   * \param which_codec 0 or 1
   * \param regno	6-bit register number
   * \param value	8-bit value
   * \returns true iff successful
   */
  bool _read_9862 (int which_codec, int regno, unsigned char *value) const;

  /*!
   * \brief Read AD9862 register.
   * \param which_codec 0 or 1
   * \param regno	6-bit register number
   * \returns register value if successful, else READ_FAILED
   */
  int  _read_9862 (int which_codec, int regno) const;

  /*!
   * \brief Write data to SPI bus peripheral.
   *
   * \param optional_header	0,1 or 2 bytes to write before buf.
   * \param enables		bitmask of peripherals to write. See usrp_spi_defs.h
   * \param format		transaction format.  See usrp_spi_defs.h SPI_FMT_*
   * \param buf			the data to write
   * \returns true iff successful
   * Writes are limited to a maximum of 64 bytes.
   *
   * If \p format specifies that optional_header bytes are present, they are
   * written to the peripheral immediately prior to writing \p buf.
   */
  bool _write_spi (int optional_header, int enables, int format, std::string buf);

  /*
   * \brief Read data from SPI bus peripheral.
   *
   * \param optional_header	0,1 or 2 bytes to write before buf.
   * \param enables		bitmask of peripheral to read. See usrp_spi_defs.h
   * \param format		transaction format.  See usrp_spi_defs.h SPI_FMT_*
   * \param len			number of bytes to read.  Must be in [0,64].
   * \param str_out             resulting string - length must be > len
   * \returns the data read if sucessful, else a zero length string.
   *
   * Reads are limited to a maximum of 64 bytes.
   *
   * If \p format specifies that optional_header bytes are present, they
   * are written to the peripheral first.  Then \p len bytes are read from
   * the peripheral and returned.
   */
  void _read_spi (int optional_header, int enables, int format, 
                         int len, char *str_out);

  /*!
   * \brief Start data transfers.
   * Called in base class to derived class order.
   */
  bool start ();

  /*!
   * \brief Stop data transfers.
   * Called in base class to derived class order.
   */
  bool stop ();
};

/*!
 * \brief class for accessing the receive side of the USRP
 */
class usrp_basic_rx : public usrp_basic 
{
private:
  fusb_devhandle	*d_devhandle;
  fusb_ephandle		*d_ephandle;
  int			 d_bytes_seen;		// how many bytes we've seen
  bool			 d_first_read;
  bool			 d_rx_enable;

protected:
  int			 d_dbid[2];		// Rx daughterboard ID's

  /*!
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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. 
   */
  usrp_basic_rx (int which_board,
		 int fusb_block_size=0,
		 int fusb_nblocks=0);  // throws if trouble

  bool set_rx_enable (bool on);
  bool rx_enable () const { return d_rx_enable; }

  bool disable_rx ();		// conditional disable, return prev state
  void restore_rx (bool on);	// conditional set

  void probe_rx_slots (bool verbose);
  int  dboard_to_slot (int dboard) { return (dboard << 1) | 1; }

public:
  ~usrp_basic_rx ();

  /*!
   * \brief invokes constructor, returns instance or 0 if trouble
   *
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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. 
   */
  static usrp_basic_rx *make (int which_board,
			      int fusb_block_size=0,
			      int fusb_nblocks=0);

  // MANIPULATORS

  /*!
   * \brief tell the fpga the rate rx samples are coming from the A/D's
   *
   * div = fpga_master_clock_freq () / sample_rate
   *
   * sample_rate is determined by a myriad of registers
   * in the 9862.  That's why you have to tell us, so
   * we can tell the fpga.
   */
  bool set_fpga_rx_sample_rate_divisor (unsigned int div);

  /*!
   * \brief read data from the D/A's via the FPGA.
   * \p len must be a multiple of 512 bytes.
   *
   * \returns the number of bytes read, or -1 on error.
   *
   * If overrun is non-NULL it will be set true iff an RX overrun is detected.
   */
  int read (void *buf, int len, bool *overrun);

  // ACCESSORS

  //! sampling rate of A/D converter
  virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M
  long adc_rate() const { return converter_rate(); }
  long adc_freq() const { return converter_rate(); }   //!< deprecated method name

  /*!
   * \brief Return daughterboard ID for given Rx daughterboard slot [0,1].
   *
   * \param which_dboard	[0,1] which Rx daughterboard
   *
   * \return daughterboard id >= 0 if successful
   * \return -1 if no daugherboard
   * \return -2 if invalid EEPROM on daughterboard
   */
  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }

  // ----------------------------------------------------------------
  // routines for controlling the Programmable Gain Amplifier
  /*!
   * \brief Set Programmable Gain Amplifier (PGA)
   *
   * \param which	which A/D [0,3]
   * \param gain_in_db	gain value (linear in dB)
   *
   * gain is rounded to closest setting supported by hardware.
   *
   * \returns true iff sucessful.
   *
   * \sa pga_min(), pga_max(), pga_db_per_step()
   */
  bool set_pga (int which, double gain_in_db);

  /*!
   * \brief Return programmable gain amplifier gain setting in dB.
   *
   * \param which	which A/D [0,3]
   */
  double pga (int which) const;

  /*!
   * \brief Return minimum legal PGA gain in dB.
   */
  double pga_min () const { return 0.0; }

  /*!
   * \brief Return maximum legal PGA gain in dB.
   */
  double pga_max () const { return 20.0; }

  /*!
   * \brief Return hardware step size of PGA (linear in dB).
   */
  double pga_db_per_step () const { return 20.0 / 20; }

  /*!
   * \brief Write direction register (output enables) for pins that go to daughterboard.
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		value to write into register
   * \param mask		which bits of value to write into reg
   *
   * Each d'board has 16-bits of general purpose i/o.
   * Setting the bit makes it an output from the FPGA to the d'board.
   *
   * This register is initialized based on a value stored in the
   * d'board EEPROM.  In general, you shouldn't be using this routine
   * without a very good reason.  Using this method incorrectly will
   * kill your USRP motherboard and/or daughterboard.
   */
  bool _write_oe (int which_dboard, int value, int mask);

  /*!
   * \brief Write daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		value to write into register
   * \param mask		which bits of value to write into reg
   */
  bool write_io (int which_dboard, int value, int mask);

  /*!
   * \brief Read daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		output
   */
  bool read_io (int which_dboard, int *value);

  /*!
   * \brief Read daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \returns register value if successful, else READ_FAILED
   */
  int read_io (int which_dboard);

  /*!
   * \brief Write auxiliary digital to analog converter.
   *
   * \param which_dboard	[0,1] which d'board
   *    			N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
   *          			SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
   * \param which_dac		[2,3] TX slots must use only 2 and 3.
   * \param value		[0,4095]
   * \returns true iff successful
   */
  bool write_aux_dac (int which_board, int which_dac, int value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param which_dboard	[0,1] which d'board
   * \param which_adc		[0,1]
   * \param value		return 12-bit value [0,4095]
   * \returns true iff successful
   */
  bool read_aux_adc (int which_dboard, int which_adc, int *value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param which_dboard	[0,1] which d'board
   * \param which_adc		[0,1]
   * \returns value in the range [0,4095] if successful, else READ_FAILED.
   */
  int read_aux_adc (int which_dboard, int which_adc);

  /*!
   * \brief returns current fusb block size
   */
  int block_size() const;

  /*!
   * \brief Enable/disable automatic DC offset removal control loop in FPGA
   *
   * \param bits  which control loops to enable
   * \param mask  which \p bits to pay attention to
   *
   * If the corresponding bit is set, enable the automatic DC
   * offset correction control loop.
   *
   * <pre>
   * The 4 low bits are significant:
   *
   *   ADC0 = (1 << 0)
   *   ADC1 = (1 << 1)
   *   ADC2 = (1 << 2)
   *   ADC3 = (1 << 3)
   * </pre>
   *
   * By default the control loop is enabled on all ADC's.
   */
  bool set_dc_offset_cl_enable(int bits, int mask);

  // called in base class to derived class order
  bool start ();
  bool stop ();
};

/*!
 * \brief class for accessing the transmit side of the USRP
 */
class usrp_basic_tx : public usrp_basic 
{
private:
  fusb_devhandle	*d_devhandle;

  int			 d_bytes_seen;		// how many bytes we've seen
  bool			 d_first_write;
  bool			 d_tx_enable;
  fusb_ephandle		*d_ephandle;

 protected:
  int			 d_dbid[2];		// Tx daughterboard ID's

  /*!
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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.
   */
  usrp_basic_tx (int which_board,
		 int fusb_block_size=0,
		 int fusb_nblocks=0);		// throws if trouble

  bool set_tx_enable (bool on);
  bool tx_enable () const { return d_tx_enable; }

  bool disable_tx ();		// conditional disable, return prev state
  void restore_tx (bool on);	// conditional set

  void probe_tx_slots (bool verbose);
  int  dboard_to_slot (int dboard) { return (dboard << 1) | 0; }

public:

  ~usrp_basic_tx ();

  /*!
   * \brief invokes constructor, returns instance or 0 if trouble
   *
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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. 
   */
  static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0);


  // MANIPULATORS

  /*!
   * \brief tell the fpga the rate tx samples are going to the D/A's
   *
   * div = fpga_master_clock_freq () * 2
   *
   * sample_rate is determined by a myriad of registers
   * in the 9862.  That's why you have to tell us, so
   * we can tell the fpga.
   */
  bool set_fpga_tx_sample_rate_divisor (unsigned int div);

  /*!
   * \brief Write data to the A/D's via the FPGA.
   *
   * \p len must be a multiple of 512 bytes.
   * \returns number of bytes written or -1 on error.
   *
   * if \p underrun is non-NULL, it will be set to true iff
   * a transmit underrun condition is detected.
   */
  int write (const void *buf, int len, bool *underrun);

  /*
   * Block until all outstanding writes have completed.
   * This is typically used to assist with benchmarking
   */
  void wait_for_completion ();

  // ACCESSORS

  //! sampling rate of D/A converter
  virtual long converter_rate() const { return fpga_master_clock_freq () * 2; } // 128M
  long dac_rate() const { return converter_rate(); }
  long dac_freq() const { return converter_rate(); }	//!< deprecated method name

  /*!
   * \brief Return daughterboard ID for given Tx daughterboard slot [0,1].
   *
   * \return daughterboard id >= 0 if successful
   * \return -1 if no daugherboard
   * \return -2 if invalid EEPROM on daughterboard
   */
  int daughterboard_id (int which_dboard) const { return d_dbid[which_dboard & 0x1]; }

  // ----------------------------------------------------------------
  // routines for controlling the Programmable Gain Amplifier
  /*!
   * \brief Set Programmable Gain Amplifier (PGA)
   *
   * \param which	which D/A [0,3]
   * \param gain_in_db	gain value (linear in dB)
   *
   * gain is rounded to closest setting supported by hardware.
   * Note that DAC 0 and DAC 1 share a gain setting as do DAC 2 and DAC 3.
   * Setting DAC 0 affects DAC 1 and vice versa.  Same with DAC 2 and DAC 3.
   *
   * \returns true iff sucessful.
   *
   * \sa pga_min(), pga_max(), pga_db_per_step()
   */
  bool set_pga (int which, double gain_in_db);

  /*!
   * \brief Return programmable gain amplifier gain in dB.
   *
   * \param which	which D/A [0,3]
   */
  double pga (int which) const;

  /*!
   * \brief Return minimum legal PGA gain in dB.
   */
  double pga_min () const { return -20.0; }

  /*!
   * \brief Return maximum legal PGA gain in dB.
   */
  double pga_max () const { return 0.0; }

  /*!
   * \brief Return hardware step size of PGA (linear in dB).
   */
  double pga_db_per_step () const { return 20.0/255; }

  /*!
   * \brief Write direction register (output enables) for pins that go to daughterboard.
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		value to write into register
   * \param mask		which bits of value to write into reg
   *
   * Each d'board has 16-bits of general purpose i/o.
   * Setting the bit makes it an output from the FPGA to the d'board.
   *
   * This register is initialized based on a value stored in the
   * d'board EEPROM.  In general, you shouldn't be using this routine
   * without a very good reason.  Using this method incorrectly will
   * kill your USRP motherboard and/or daughterboard.
   */
  bool _write_oe (int which_dboard, int value, int mask);

  /*!
   * \brief Write daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		value to write into register
   * \param mask		which bits of value to write into reg
   */
  bool write_io (int which_dboard, int value, int mask);

  /*!
   * \brief Read daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \param value		return value
   */
  bool read_io (int which_dboard, int *value);

  /*!
   * \brief Read daughterboard i/o pin value
   *
   * \param which_dboard	[0,1] which d'board
   * \returns register value if successful, else READ_FAILED
   */
  int read_io (int which_dboard);

  /*!
   * \brief Write auxiliary digital to analog converter.
   *
   * \param which_dboard	[0,1] which d'board
   *    			N.B., SLOT_TX_A and SLOT_RX_A share the same AUX DAC's.
   *          			SLOT_TX_B and SLOT_RX_B share the same AUX DAC's.
   * \param which_dac		[2,3] TX slots must use only 2 and 3.
   * \param value		[0,4095]
   * \returns true iff successful
   */
  bool write_aux_dac (int which_board, int which_dac, int value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param which_dboard	[0,1] which d'board
   * \param which_adc		[0,1]
   * \param value		return 12-bit value [0,4095]
   * \returns true iff successful
   */
  bool read_aux_adc (int which_dboard, int which_adc, int *value);

  /*!
   * \brief Read auxiliary analog to digital converter.
   *
   * \param which_dboard	[0,1] which d'board
   * \param which_adc		[0,1]
   * \returns value in the range [0,4095] if successful, else READ_FAILED.
   */
  int read_aux_adc (int which_dboard, int which_adc);

  /*!
   * \brief returns current fusb block size
   */
  int block_size() const;

  // called in base class to derived class order
  bool start ();
  bool stop ();
};


//////////////// usrp_standard.h ///////////////

/*!
 * \brief standard usrp RX class.  
 *
 * Assumes digital down converter in FPGA
 */
class usrp_standard_rx : public usrp_basic_rx
{
 private:
  unsigned int		d_decim_rate;
  int			d_nchan;
  int			d_sw_mux;
  int			d_hw_mux;
  double		d_rx_freq[MAX_CHAN_RX];

 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
		    );  // throws if trouble

  bool write_hw_mux_reg ();

 public:

  enum {
    FPGA_MODE_NORMAL     = 0x00,
    FPGA_MODE_LOOPBACK   = 0x01,
    FPGA_MODE_COUNTING   = 0x02
  };

  ~usrp_standard_rx ();

  /*!
   * \brief invokes constructor, returns instance or 0 if trouble
   *
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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. 
   */
  static usrp_standard_rx *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
				 );
  /*!
   * \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);

  /*!
   * \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);

  // 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 standard usrp TX class.
 *
 * Uses digital upconverter (coarse & fine modulators) in AD9862...
 */
class usrp_standard_tx : public usrp_basic_tx
{
 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:
  unsigned int		d_interp_rate;
  int			d_nchan;
  int			d_sw_mux;
  int			d_hw_mux;
  double		d_tx_freq[MAX_CHAN_TX];
  coarse_mod_t		d_coarse_mod[MAX_CHAN_TX];
  unsigned char		d_tx_modulator_shadow[MAX_CHAN_TX];

  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
		    );	// throws if trouble

  bool write_hw_mux_reg ();

 public:
  ~usrp_standard_tx ();

  /*!
   * \brief invokes constructor, returns instance or 0 if trouble
   *
   * \param which_board	     Which USRP board on usb (not particularly useful; use 0)
   * \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. 
   */
  static usrp_standard_tx *make (int which_board,
				 unsigned int interp_rate,
				 int nchan = 1,
				 int mux = -1,
				 int fusb_block_size = 0,
				 int fusb_nblocks = 0
				 );

  /*!
   * \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);

  /*!
   * \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;

  // called in base class to derived class order
  bool start ();
  bool stop ();
};

/////////////////////// functions added by Michael Perrott ///////////
double set_adf4360_freq(struct usb_dev_handle *d_udh, int dbid_val, 
                        double freq, int which_slot);
void set_flex_io(usrp_standard_tx *utx, int which_slot, char *control_string);
void set_flex_io(usrp_standard_rx *urx, int which_slot, char *control_string);
//////////////////////////////////////////////////////////////////////


///////////////// usrp_interfaces.h ///////////////

/*
 * We've now split the USRP into 3 separate interfaces.
 *
 * Interface 0 contains only ep0 and is used for command and status.
 * Interface 1 is the Tx path and it uses ep2 OUT BULK.
 * Interface 2 is the Rx path and it uses ep6 IN BULK.
 */
 
#define	USRP_CMD_INTERFACE		0
#define	USRP_CMD_ALTINTERFACE		0
#define	USRP_CMD_ENDPOINT		0

#define	USRP_TX_INTERFACE		1
#define	USRP_TX_ALTINTERFACE		0
#define	USRP_TX_ENDPOINT		2	// streaming data from host to FPGA

#define	USRP_RX_INTERFACE		2
#define	USRP_RX_ALTINTERFACE		0
#define	USRP_RX_ENDPOINT		6	// streaming data from FPGA to host


///////////////// fpga_regs_standard.h /////////////


// This file defines registers common to all FPGA configurations.
// Registers 0 to 31 are reserved for use in this file.


// The FPGA needs to know the rate that samples are coming from and
// going to the A/D's and D/A's.  div = 128e6 / sample_rate

#define	FR_TX_SAMPLE_RATE_DIV	 0
#define	FR_RX_SAMPLE_RATE_DIV	 1

// 2 is available.
// 3 is used below for FR_ATR_CTL.

#define	FR_MASTER_CTRL		 4	// master enable and reset controls
#  define  bmFR_MC_ENABLE_TX		(1 << 0)
#  define  bmFR_MC_ENABLE_RX		(1 << 1)
#  define  bmFR_MC_RESET_TX		(1 << 2)
#  define  bmFR_MC_RESET_RX		(1 << 3)

// i/o direction registers for pins that go to daughterboards.
// Setting the bit makes it an output from the FPGA to the d'board.
// top 16 is mask, low 16 is value

#define	FR_OE_0			 5	// slot 0
#define	FR_OE_1			 6
#define	FR_OE_2			 7
#define	FR_OE_3			 8

// i/o registers for pins that go to daughterboards.
// top 16 is a mask, low 16 is value

#define	FR_IO_0			 9	// slot 0
#define	FR_IO_1			10
#define	FR_IO_2			11
#define	FR_IO_3			12

#define	FR_MODE			13
#  define  bmFR_MODE_NORMAL		      0
#  define  bmFR_MODE_LOOPBACK		(1 << 0)	// enable digital loopback
#  define  bmFR_MODE_RX_COUNTING	(1 << 1)	// Rx is counting


// If the corresponding bit is set, internal FPGA debug circuitry
// controls the i/o pins for the associated bank of daughterboard
// i/o pins.  Typically used for debugging FPGA designs.

#define FR_DEBUG_EN             14
#  define bmFR_DEBUG_EN_TX_A           (1 << 0)        // debug controls TX_A i/o
#  define bmFR_DEBUG_EN_RX_A           (1 << 1)        // debug controls RX_A i/o
#  define bmFR_DEBUG_EN_TX_B           (1 << 2)        // debug controls TX_B i/o
#  define bmFR_DEBUG_EN_RX_B           (1 << 3)        // debug controls RX_B i/o


// If the corresponding bit is set, enable the automatic DC
// offset correction control loop.
//
// The 4 low bits are significant:
//
//   ADC0 = (1 << 0)
//   ADC1 = (1 << 1)
//   ADC2 = (1 << 2)
//   ADC3 = (1 << 3)
//
// This control loop works if the attached daugherboard blocks DC.
// Currently all daughterboards do block DC.  This includes:
// basic rx, dbs_rx, tv_rx, flex_xxx_rx.

#define FR_DC_OFFSET_CL_EN	15			// DC Offset Control Loop Enable


// offset corrections for ADC's and DAC's (2's complement)

#define	FR_ADC_OFFSET_0	 	16
#define	FR_ADC_OFFSET_1		17
#define	FR_ADC_OFFSET_2	 	18
#define	FR_ADC_OFFSET_3		19


// ------------------------------------------------------------------------
// Automatic Transmit/Receive switching
//
// If automatic transmit/receive (ATR) switching is enabled in the
// FR_ATR_CTL register, the presence or absence of data in the FPGA
// transmit fifo selects between two sets of values for each of the 4
// banks of daughterboard i/o pins.
//
// Each daughterboard slot has 3 16-bit registers associated with it:
//   FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_*
//
// FR_ATR_MASK_{0,1,2,3}: 
//
//   These registers determine which of the daugherboard i/o pins are
//   affected by ATR switching.  If a bit in the mask is set, the
//   corresponding i/o bit is controlled by ATR, else it's output
//   value comes from the normal i/o pin output register:
//   FR_IO_{0,1,2,3}.
//
// FR_ATR_TXVAL_{0,1,2,3}:
// FR_ATR_RXVAL_{0,1,2,3}:
//
//   If the Tx fifo contains data, then the bits from TXVAL that are
//   selected by MASK are output.  Otherwise, the bits from RXVAL that
//   are selected by MASK are output.
                      
#define FR_ATR_MASK_0		20	// slot 0
#define	FR_ATR_TXVAL_0		21
#define FR_ATR_RXVAL_0		22

#define FR_ATR_MASK_1		23	// slot 1
#define	FR_ATR_TXVAL_1		24
#define FR_ATR_RXVAL_1		25

#define FR_ATR_MASK_2		26	// slot 2
#define	FR_ATR_TXVAL_2		27
#define FR_ATR_RXVAL_2		28

#define FR_ATR_MASK_3		29	// slot 3
#define	FR_ATR_TXVAL_3		30
#define FR_ATR_RXVAL_3		31

// Auto Transmit/Receive 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)                |E|
// +-------------------------------------------------------------+-+
//

#define FR_ATR_CTL		 3
#define bmFR_ATR_CTL_EN		(1 <<  0)


///////////////// fpga_regs_standard.h /////////////

// Register numbers 0 to 31 are reserved for use in fpga_regs_common.h.
// Registers 64 to 79 are available for custom FPGA builds.


// DDC / DUC

#define	FR_INTERP_RATE		32	// [1,1024]
#define	FR_DECIM_RATE		33	// [1,256]

// DDC center freq

#define FR_RX_FREQ_0		34
#define FR_RX_FREQ_1		35
#define FR_RX_FREQ_2		36
#define FR_RX_FREQ_3		37

// See below for DDC Starting Phase

// ------------------------------------------------------------------------
//  configure FPGA Rx mux
//
//    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
// +-----------------------+-------+-------+-------+-------+-+-----+
// |      must be zero     | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
// +-----------------------+-------+-------+-------+-------+-+-----+
//
// There are a maximum of 4 digital downconverters in the the FPGA.
// Each DDC has two 16-bit inputs, I and Q, and two 16-bit outputs, I & Q.
//
// DDC I inputs are specified by the two bit fields I3, I2, I1 & I0
//
//   0 = DDC input is from ADC 0
//   1 = DDC input is from ADC 1
//   2 = DDC input is from ADC 2
//   3 = DDC input is from ADC 3
//
// If Z == 1, all DDC Q inputs are set to zero
// If Z == 0, DDC Q inputs are specified by the two bit fields Q3, Q2, Q1 & Q0
//
// NCH specifies the number of complex channels that are sent across
// the USB.  The legal values are 1, 2 or 4, corresponding to 2, 4 or
// 8 16-bit values.

#define	FR_RX_MUX		38

// ------------------------------------------------------------------------
//  configure FPGA Tx Mux.
//
//    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 |0| NCH |
// +-----------------------------------------------+-------+-+-----+
//
// NCH specifies the number of complex channels that are sent across
// the USB.  The legal values are 1 or 2, corresponding to 2 or 4
// 16-bit values.
//
// There are two interpolators with complex inputs and outputs.
// There are four DACs.  (We use the DUC in each AD9862.)
//
// 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

#define	FR_TX_MUX		39

// ------------------------------------------------------------------------
// REFCLK control
//
// Control whether a reference clock is sent to the daughterboards,
// and what frequency.  The refclk is sent on d'board i/o pin 0.
//
//    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)           |E|   DIVISOR  |
// +-----------------------------------------------+-+------------+

//
// Bit 7  -- 1 turns on refclk, 0 allows IO use
// Bits 6:0 Divider value

#define FR_TX_A_REFCLK          40
#define FR_RX_A_REFCLK          41
#define FR_TX_B_REFCLK          42
#define FR_RX_B_REFCLK          43

#  define bmFR_REFCLK_EN	   0x80
#  define bmFR_REFCLK_DIVISOR_MASK 0x7f

// ------------------------------------------------------------------------
// DDC Starting Phase

#define FR_RX_PHASE_0		44
#define FR_RX_PHASE_1		45
#define FR_RX_PHASE_2		46
#define FR_RX_PHASE_3		47

// ------------------------------------------------------------------------
// Tx 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)            |  FMT  |
// +-------------------------------------------------------+-------+
//
//  FMT values:

#define FR_TX_FORMAT		48
#  define bmFR_TX_FORMAT_16_IQ		0	// 16-bit I, 16-bit Q

// ------------------------------------------------------------------------
// 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 |
// +-----------------------------------------+-+-+---------+-------+
//
//  FMT values:

#define FR_RX_FORMAT		49

#  define bmFR_RX_FORMAT_SHIFT_MASK	(0x0f <<  0)	// arithmetic right shift [0, 15]
#  define bmFR_RX_FORMAT_SHIFT_SHIFT	0
#  define bmFR_RX_FORMAT_WIDTH_MASK	(0x1f <<  4)    // data width in bits [1, 16] (not all valid)
#  define bmFR_RX_FORMAT_WIDTH_SHIFT    4
#  define bmFR_RX_FORMAT_WANT_Q		(0x1  <<  9)    // deliver both I & Q, else just I
#  define bmFR_RX_FORMAT_BYPASS_HB	(0x1  << 10)    // bypass half-band filter

// Soon the valid combinations will be:
//
//   B  Q  WIDTH  SHIFT
//   x  0    16     0
//   x  1    16     0
//   x  0     8     8
//   x  1     8     8

// Possible future values of WIDTH = {4, 2, 1}
// 12 takes a bit more work, since we need to know packet alignment.

// ------------------------------------------------------------------------
// FIXME register numbers 50 to 63 are available

// ------------------------------------------------------------------------
// Registers 64 to 79 are reserved for user custom FPGA builds.
// The standard USRP software will not touch these.

#define FR_USER_0	64
#define FR_USER_1	65
#define FR_USER_2	66
#define FR_USER_3	67
#define FR_USER_4	68
#define FR_USER_5	69
#define FR_USER_6	70
#define FR_USER_7	71
#define FR_USER_8	72
#define FR_USER_9	73
#define FR_USER_10	74
#define FR_USER_11	75
#define FR_USER_12	76
#define FR_USER_13	77
#define FR_USER_14	78
#define FR_USER_15	79


///////////////// ad9862.h /////////////
/*
 * Analog Devices AD9862 registers and some fields
 */

#define BEGIN_AD9862	namespace ad9862 {
#define	END_AD962	}
#define	DEF static const int

BEGIN_AD9862;

DEF REG_GENERAL		=  0;
DEF REG_RX_PWR_DN	=  1;
DEF	RX_PWR_DN_VREF_DIFF		= (1 << 7);
DEF	RX_PWR_DN_VREF			= (1 << 6);
DEF	RX_PWR_DN_RX_DIGIGAL		= (1 << 5);
DEF	RX_PWR_DN_RX_B			= (1 << 4);
DEF	RX_PWR_DN_RX_A			= (1 << 3);
DEF	RX_PWR_DN_BUF_B			= (1 << 2);
DEF	RX_PWR_DN_BUF_A			= (1 << 1);
DEF	RX_PWR_DN_ALL			= (1 << 0);

DEF REG_RX_A		=  2;	// bypass input buffer / RxPGA
DEF REG_RX_B		=  3;	// pypass input buffer / RxPGA
DEF	RX_X_BYPASS_INPUT_BUFFER	= (1 << 7);

DEF REG_RX_MISC		=  4;
DEF	RX_MISC_HS_DUTY_CYCLE		= (1 << 2);
DEF	RX_MISC_SHARED_REF		= (1 << 1);
DEF	RX_MISC_CLK_DUTY		= (1 << 0);

DEF REG_RX_IF		=  5;
DEF	RX_IF_THREE_STATE		= (1 << 4);
DEF	RX_IF_USE_CLKOUT1		= (0 << 3);	
DEF	RX_IF_USE_CLKOUT2		= (1 << 3);	// aka Rx Retime
DEF	RX_IF_2S_COMP			= (1 << 2);
DEF	RX_IF_INV_RX_SYNC		= (1 << 1);
DEF	RX_IF_MUX_OUT			= (1 << 0);

DEF REG_RX_DIGITAL	=  6;
DEF	RX_DIGITAL_2_CHAN		= (1 << 3);
DEF	RX_DIGITAL_KEEP_MINUS_VE	= (1 << 2);
DEF	RX_DIGITAL_HILBERT		= (1 << 1);
DEF	RX_DIGITAL_DECIMATE		= (1 << 0);

DEF REG_RESERVED_7	=  7;

DEF REG_TX_PWR_DN	=  8;
DEF	TX_PWR_DN_ALT_TIMING_MODE	= (1 << 5);
DEF	TX_PWR_DN_TX_OFF_ENABLE		= (1 << 4);
DEF	TX_PWR_DN_TX_DIGITAL		= (1 << 3);
DEF	TX_PWR_DN_TX_ANALOG_B		= 0x4;
DEF	TX_PWR_DN_TX_ANALOG_A		= 0x2;
DEF	TX_PWR_DN_TX_ANALOG_BOTH	= 0x7;

DEF REG_RESERVED_9	=  9;

DEF REG_TX_A_OFFSET_LO	= 10;
DEF REG_TX_A_OFFSET_HI	= 11;
DEF REG_TX_B_OFFSET_LO	= 12;
DEF REG_TX_B_OFFSET_HI	= 13;

DEF REG_TX_A_GAIN	= 14;	// fine trim for matching
DEF REG_TX_B_GAIN	= 15;	// fine trim for matching
DEF	TX_X_GAIN_COARSE_FULL		= (3 << 6);
DEF	TX_X_GAIN_COARSE_1_HALF		= (1 << 6);
DEF	TX_X_GAIN_COARSE_1_ELEVENTH	= (0 << 6);

DEF REG_TX_PGA		= 16;	// 20 dB continuous gain in 0.1 dB steps
				// 0x00 = min gain (-20 dB)
				// 0xff = max gain (  0 dB)

DEF REG_TX_MISC		= 17;
DEF	TX_MISC_SLAVE_ENABLE		= (1 << 1);
DEF	TX_MISC_TX_PGA_FAST		= (1 << 0);

DEF REG_TX_IF		= 18;
DEF	TX_IF_USE_CLKOUT2		= (0 << 6);
DEF	TX_IF_USE_CLKOUT1		= (1 << 6);	// aka Tx Retime
DEF	TX_IF_I_FIRST			= (0 << 5);
DEF	TX_IF_Q_FIRST			= (1 << 5);
DEF	TX_IF_INV_TX_SYNC		= (1 << 4);
DEF	TX_IF_2S_COMP			= (1 << 3);
DEF	TX_IF_INVERSE_SAMPLE		= (1 << 2);
DEF	TX_IF_TWO_EDGES			= (1 << 1);
DEF	TX_IF_INTERLEAVED		= (1 << 0);

DEF REG_TX_DIGITAL	= 19;
DEF	TX_DIGITAL_2_DATA_PATHS		= (1 << 4);
DEF	TX_DIGITAL_KEEP_NEGATIVE	= (1 << 3);
DEF	TX_DIGITAL_HILBERT		= (1 << 2);
DEF	TX_DIGITAL_INTERPOLATE_NONE	= 0x0;
DEF	TX_DIGITAL_INTERPOLATE_2X	= 0x1;
DEF	TX_DIGITAL_INTERPOLATE_4X	= 0x2;

DEF REG_TX_MODULATOR	= 20;
DEF	TX_MODULATOR_NEG_FINE_TUNE	= (1 << 5);
DEF	TX_MODULATOR_DISABLE_NCO	= (0 << 4);
DEF	TX_MODULATOR_ENABLE_NCO		= (1 << 4);	// aka Fine Mode
DEF	TX_MODULATOR_REAL_MIX_MODE	= (1 << 3);
DEF	TX_MODULATOR_NEG_COARSE_TUNE	= (1 << 2);
DEF	TX_MODULATOR_COARSE_MODULATION_NONE	= 0x0;
DEF	TX_MODULATOR_COARSE_MODULATION_F_OVER_4	= 0x1;
DEF	TX_MODULATOR_COARSE_MODULATION_F_OVER_8 = 0x2;
DEF	TX_MODULATOR_CM_MASK		        = 0x7;


DEF REG_TX_NCO_FTW_7_0	= 21;
DEF REG_TX_NCO_FTW_15_8	= 22;
DEF REG_TX_NCO_FTW_23_16= 23;

DEF REG_DLL		= 24;
DEF	DLL_DISABLE_INTERNAL_XTAL_OSC	= (1 << 6);	// aka Input Clock Ctrl
DEF	DLL_ADC_DIV2			= (1 << 5);
DEF	DLL_MULT_1X			= (0 << 3);
DEF	DLL_MULT_2X			= (1 << 3);
DEF	DLL_MULT_4X			= (2 << 3);
DEF	DLL_PWR_DN			= (1 << 2);
// undefined bit			= (1 << 1);
DEF	DLL_FAST			= (1 << 0);

DEF REG_CLKOUT		= 25;
DEF	CLKOUT2_EQ_DLL			= (0 << 6);
DEF	CLKOUT2_EQ_DLL_OVER_2		= (1 << 6);
DEF	CLKOUT2_EQ_DLL_OVER_4		= (2 << 6);
DEF	CLKOUT2_EQ_DLL_OVER_8		= (3 << 6);
DEF	CLKOUT_INVERT_CLKOUT2		= (1 << 5);
DEF	CLKOUT_DISABLE_CLKOUT2		= (1 << 4);
// undefined bit			= (1 << 3);
// undefined bit			= (1 << 2);
DEF	CLKOUT_INVERT_CLKOUT1		= (1 << 1);
DEF	CLKOUT_DISABLE_CLKOUT1		= (1 << 0);

DEF REG_AUX_ADC_A2_LO	= 26;
DEF REG_AUX_ADC_A2_HI	= 27;
DEF REG_AUX_ADC_A1_LO	= 28;
DEF REG_AUX_ADC_A1_HI	= 29;
DEF REG_AUX_ADC_B2_LO	= 30;
DEF REG_AUX_ADC_B2_HI	= 31;
DEF REG_AUX_ADC_B1_LO	= 32;
DEF REG_AUX_ADC_B1_HI	= 33;

DEF REG_AUX_ADC_CTRL	= 34;
DEF	AUX_ADC_CTRL_AUX_SPI		= (1 << 7);
DEF	AUX_ADC_CTRL_SELBNOTA		= (1 << 6);
DEF	AUX_ADC_CTRL_REFSEL_B		= (1 << 5);
DEF	AUX_ADC_CTRL_SELECT_B2 		= (0 << 4);
DEF	AUX_ADC_CTRL_SELECT_B1		= (1 << 4);
DEF	AUX_ADC_CTRL_START_B		= (1 << 3);
DEF	AUX_ADC_CTRL_REFSEL_A		= (1 << 2);
DEF	AUX_ADC_CTRL_SELECT_A2		= (0 << 1);
DEF	AUX_ADC_CTRL_SELECT_A1		= (1 << 1);
DEF	AUX_ADC_CTRL_START_A   		= (1 << 0);

DEF REG_AUX_ADC_CLK	= 35;
DEF	AUX_ADC_CLK_CLK_OVER_4		= (1 << 0);

DEF REG_AUX_DAC_A	= 36;
DEF REG_AUX_DAC_B	= 37;
DEF REG_AUX_DAC_C	= 38;

DEF REG_AUX_DAC_UPDATE	= 39;
DEF	AUX_DAC_UPDATE_SLAVE_ENABLE	= (1 << 7);
DEF	AUX_DAC_UPDATE_C		= (1 << 2);
DEF	AUX_DAC_UPDATE_B		= (1 << 1);
DEF	AUX_DAC_UPDATE_A		= (1 << 0);

DEF REG_AUX_DAC_PWR_DN	= 40;
DEF	AUX_DAC_PWR_DN_C		= (1 << 2);
DEF	AUX_DAC_PWR_DN_B		= (1 << 1);
DEF	AUX_DAC_PWR_DN_A		= (1 << 0);

DEF REG_AUX_DAC_CTRL	= 41;
DEF	AUX_DAC_CTRL_INV_C		= (1 << 4);
DEF	AUX_DAC_CTRL_INV_B		= (1 << 2);
DEF	AUX_DAC_CTRL_INV_A		= (1 << 0);

DEF REG_SIGDELT_LO	= 42;
DEF REG_SIGDELT_HI	= 43;

// 44 to 48 reserved

DEF REG_ADC_LOW_PWR_LO	= 49;
DEF REG_ADC_LOW_PWR_HI	= 50;

// 51 to 62 reserved

DEF REG_CHIP_ID		= 63;


END_AD962;

#undef DEF
#undef BEGIN_AD9862
#undef END_AD962


///////////  usrp_spi_defs.h //////////

/*
 * defines for the VRQ_SPI_READ and VRQ_SPI_WRITE commands
 *
 * SPI == "Serial Port Interface".  SPI is a 3 wire bus plus a
 * separate enable for each peripheral.  The common lines are SCLK,
 * SDI and SDO.  The FX2 always drives SCLK and SDI, the clock and
 * data lines from the FX2 to the peripheral.  When enabled, a
 * peripheral may drive SDO, the data line from the peripheral to the
 * FX2.
 *
 * The SPI_READ and SPI_WRITE commands are formatted identically.
 * Each specifies which peripherals to enable, whether the bits should
 * be transmistted Most Significant Bit first or Least Significant Bit
 * first, the number of bytes in the optional header, and the number
 * of bytes to read or write in the body.
 *
 * The body is limited to 64 bytes.  The optional header may contain
 * 0, 1 or 2 bytes.  For an SPI_WRITE, the header bytes are
 * transmitted to the peripheral followed by the the body bytes.  For
 * an SPI_READ, the header bytes are transmitted to the peripheral,
 * then len bytes are read back from the peripheral.
 */

/*
 * SPI_FMT_* goes in wIndexL
 */
#define SPI_FMT_xSB_MASK	(1 << 7)
#  define	SPI_FMT_LSB	(1 << 7)	// least signficant bit first
#  define	SPI_FMT_MSB	(0 << 7)	// most significant bit first
#define	SPI_FMT_HDR_MASK	(3 << 5)
#  define	SPI_FMT_HDR_0	(0 << 5)	// 0 header bytes
#  define	SPI_FMT_HDR_1	(1 << 5)	// 1 header byte
#  define	SPI_FMT_HDR_2	(2 << 5)	// 2 header bytes

/*
 * SPI_ENABLE_*  goes in wIndexH
 *
 * For the software interface, the enables are active high.
 * For reads, it's an error to have more than one enable set.
 *
 * [FWIW, the hardware implements them as active low.  Don't change the
 * definitions of these.  They are related to usrp_rev1_regs.h]
 */
#define	SPI_ENABLE_FPGA		0x01	// select FPGA
#define	SPI_ENABLE_CODEC_A	0x02	// select AD9862 A
#define	SPI_ENABLE_CODEC_B	0x04	// select AD9862 B
#define	SPI_ENABLE_reserved	0x08
#define	SPI_ENABLE_TX_A		0x10	// select d'board TX A
#define	SPI_ENABLE_RX_A		0x20	// select d'board RX A
#define	SPI_ENABLE_TX_B		0x40	// select d'board TX B
#define	SPI_ENABLE_RX_B		0x80	// select d'board RX B

/*
 * If there's one header byte, it goes in wValueL.
 *
 * If there are two header bytes, they go in wValueH | wValueL.
 * The transmit order of the bytes (and bits within them) is 
 * determined by SPI_FMT_*SB
 */

/////////// usrp_commands.h ////////////


#define	MAX_EP0_PKTSIZE		       64	// max size of EP0 packet on FX2

// ----------------------------------------------------------------
//			Vendor bmRequestType's
// ----------------------------------------------------------------

#define	VRT_VENDOR_IN			0xC0
#define	VRT_VENDOR_OUT			0x40

// ----------------------------------------------------------------
//			  USRP Vendor Requests
//
// Note that Cypress reserves [0xA0,0xAF].
// 0xA0 is the firmware load function.
// ----------------------------------------------------------------


// IN commands

#define	VRQ_GET_STATUS			0x80
#define		GS_TX_UNDERRUN			0	// wIndexL	// returns 1 byte
#define		GS_RX_OVERRUN			1	// wIndexL	// returns 1 byte

#define	VRQ_I2C_READ			0x81		// wValueL: i2c address; length: how much to read

#define	VRQ_SPI_READ			0x82		// wValue: optional header bytes
							// wIndexH:	enables
							// wIndexL:	format
							// len: how much to read

// OUT commands

#define	VRQ_SET_LED			0x01		// wValueL off/on {0,1}; wIndexL: which {0,1}

#define	VRQ_FPGA_LOAD			0x02
#  define	FL_BEGIN			0	// wIndexL: begin fpga programming cycle.  stalls if trouble.
#  define	FL_XFER				1	// wIndexL: xfer up to 64 bytes of data
#  define	FL_END				2	// wIndexL: end programming cycle, check for success.
							//          stalls endpoint if trouble.

#define	VRQ_FPGA_WRITE_REG		0x03		// wIndexL: regno; data: 32-bit regval MSB first
#define	VRQ_FPGA_SET_RESET		0x04		// wValueL: {0,1}
#define	VRQ_FPGA_SET_TX_ENABLE		0x05		// wValueL: {0,1}
#define	VRQ_FPGA_SET_RX_ENABLE		0x06		// wValueL: {0,1}
// see below VRQ_FPGA_SET_{TX,RX}_RESET

#define	VRQ_SET_SLEEP_BITS		0x07		// wValueH: mask; wValueL: bits.  set bits given by mask to bits

#  define	SLEEP_ADC0			0x01
#  define	SLEEP_ADC1			0x02
#  define	SLEEP_DAC0			0x04
#  define	SLEEP_DAC1			0x08

#define	VRQ_I2C_WRITE			0x08		// wValueL: i2c address; data: data

#define	VRQ_SPI_WRITE			0x09		// wValue: optional header bytes
							// wIndexH:	enables
							// wIndexL:	format
							// len: how much to write

#define	VRQ_FPGA_SET_TX_RESET		0x0a		// wValueL: {0, 1}
#define	VRQ_FPGA_SET_RX_RESET		0x0b		// wValueL: {0, 1}


// -------------------------------------------------------------------
// we store the hashes at fixed addresses in the FX2 internal memory

#define	  USRP_HASH_SLOT_0_ADDR			0xe1e0
#define	  USRP_HASH_SLOT_1_ADDR			0xe1f0


//////////// usrp_ids.h /////////////

/*
 * USB Vendor and Product IDs that we use
 *
 * (keep in sync with usb_descriptors.a51)
 */

#define	USB_VID_CYPRESS			0x04b4
#define	USB_PID_CYPRESS_FX2		0x8613


#define	USB_VID_FSF			0xfffe	  // Free Software Folks
#define	USB_PID_FSF_EXP_0		0x0000	  // Experimental 0
#define	USB_PID_FSF_EXP_1		0x0001	  // Experimental 1
#define	USB_PID_FSF_USRP		0x0002	  // Universal Software Radio Peripheral
#define	USB_PID_FSF_USRP_reserved	0x0003	  // Universal Software Radio Peripheral
#define	USB_PID_FSF_SSRP		0x0004	  // Simple Software Radio Peripheral
#define	USB_PID_FSF_SSRP_reserved	0x0005	  // Simple Software Radio Peripheral
#define USB_PID_FSF_LBNL_UXO            0x0018    // http://recycle.lbl.gov/~ldoolitt/uxo/


#define	USB_DID_USRP_0			0x0000	  // unconfigured rev 0 USRP
#define	USB_DID_USRP_1			0x0001	  // unconfigured rev 1 USRP
#define	USB_DID_USRP_2			0x0002	  // unconfigured rev 2 USRP


//////////////  usrp_i2c_addr.h //////////////

// I2C addresses

#define I2C_DEV_EEPROM	0x50		// 24LC02[45]:  7-bits 1010xxx

#define	I2C_ADDR_BOOT	(I2C_DEV_EEPROM	| 0x0)
#define	I2C_ADDR_TX_A	(I2C_DEV_EEPROM | 0x4)
#define	I2C_ADDR_RX_A	(I2C_DEV_EEPROM | 0x5)
#define	I2C_ADDR_TX_B	(I2C_DEV_EEPROM	| 0x6)
#define	I2C_ADDR_RX_B	(I2C_DEV_EEPROM | 0x7)


// format of FX2 BOOT EEPROM
//	00: 0xC0	code for ``Read IDs from EEPROM''
//	01: 0xFE	USB Vendor ID (LSB)
//	02: 0xFF	USB Vendor ID (MSB)
//	03: 0x02	USB Product ID (LSB)
//	04: 0x00	USB Product ID (MSB)
//	05: 0x01	USB Device ID (LSB)	// rev1
//	06: 0x00	USB Device ID (MSB)	// 0 = unconfig'd (no firmware)
//	07: 0x00	option byte


// format of daughterboard EEPROM
//	00: 0xDB	code for ``I'm a daughterboard''
//	01:   ..	Daughterboard ID (LSB)
//	02:   ..	Daughterboard ID (MSB)
//	03:   ..	io bits  7-0 direction (bit set if it's an output from m'board)
//	04:   ..	io bits 15-8 direction (bit set if it's an output from m'board)
//	05:   ..	ADC0 DC offset correction (LSB)
//	06:   ..	ADC0 DC offset correction (MSB)
//	07:   ..	ADC1 DC offset correction (LSB)
//	08:   ..	ADC1 DC offset correction (MSB)
// 	...
//	1f:   ..	negative of the sum of bytes [0x00, 0x1e]

#define	DB_EEPROM_MAGIC		0x00
#define	  DB_EEPROM_MAGIC_VALUE			0xDB
#define	DB_EEPROM_ID_LSB		0x01
#define	DB_EEPROM_ID_MSB		0x02
#define	DB_EEPROM_OE_LSB		0x03
#define	DB_EEPROM_OE_MSB		0x04
#define	DB_EEPROM_OFFSET_0_LSB		0x05	// offset correction for ADC or DAC 0
#define	DB_EEPROM_OFFSET_0_MSB		0x06
#define	DB_EEPROM_OFFSET_1_LSB		0x07	// offset correction for ADC or DAC 1
#define	DB_EEPROM_OFFSET_1_MSB		0x08
#define	DB_EEPROM_CHKSUM		0x1f

#define	DB_EEPROM_CLEN			0x20	// length of common portion of eeprom

#define	DB_EEPROM_CUSTOM_BASE		DB_EEPROM_CLEN	// first avail offset for
							//   daughterboard specific use

//////////////////// USRP Object for CppSim ////////////////
/////////////////// Created by Michael Perrott /////////////

class USRPTransmitObject
{
public:
  USRPTransmitObject(double usrp_sample_rate, double Ts);
  ~USRPTransmitObject();
  void stream_dac_out(double tx_a,double tx_b);
  void set_dco_freq(double dco_freq_in);
  void set_vco_freq(double vco_freq_in);
  void set_dac_gain(double dac_gain_in);
  void set_slot(int slot_in);
  void enable_rf_card();
  double get_vco_freq();
// static variables
  usrp_standard_tx *utx;
  short *buf;
  int count;
  int N;
  int dbid;
  int size_of_buf;
  int sampling_ratio;
  int sampling_count;
  double actual_vco_freq;
// parameters
  double vco_freq;
  double dac_gain;
  double sample_rate;
  double dco_freq;
  int slot;
private:
};

class USRPReceiveObject
{
public:
  USRPReceiveObject(double usrp_sample_rate, double Ts);
  ~USRPReceiveObject();
  void stream_adc_in(double *rx_a,double *rx_b);
  void set_dco_freq(double dco_freq_in);
  void set_vco_freq(double vco_freq_in);
  void set_mixer_gain(double mixer_gain_in);
  void set_adc_gain(double adc_gain_in);
  void enable_offset_cancel();
  void disable_offset_cancel();
  void set_slot(int slot_in);
  void enable_rf_card();
  double get_vco_freq();
// static variables
  usrp_standard_rx *urx;
  short *buf;
  int count;
  int N;
  int dbid;
  int size_of_buf;
  int sampling_ratio;
  int sampling_count;
  double actual_vco_freq;
// parameters
  double vco_freq;
  double adc_gain;
  double sample_rate;
  double dco_freq;
  double mixer_gain;
  int offset_cancel;
  int slot;
private:
};
