From 158caeaa92df7ffdf363236985f4b8e7825f3950 Mon Sep 17 00:00:00 2001 From: ttsou Date: Wed, 9 Sep 2009 11:02:41 -0400 Subject: Added autotools header generation and build time version checking --- config/usrp_fusb_tech.m4 | 5 +- config/usrp_libusb.m4 | 79 ++- usrp/host/Makefile.am | 2 +- usrp/host/include/usrp/Makefile.am | 10 + usrp/host/include/usrp/usrp_basic.h | 1000 -------------------------------- usrp/host/include/usrp/usrp_basic.h.in | 960 ++++++++++++++++++++++++++++++ usrp/host/include/usrp/usrp_prims.h | 309 ---------- usrp/host/include/usrp/usrp_prims.h.in | 291 ++++++++++ usrp/host/lib/fusb.h | 9 +- usrp/host/lib/usrp_basic_common.cc | 8 +- usrp/host/lib/usrp_basic_libusb.cc | 1 - usrp/host/lib/usrp_prims_common.cc | 18 +- usrp/host/lib/usrp_prims_libusb.cc | 25 +- usrp/host/lib/usrp_prims_libusb1.cc | 20 +- 14 files changed, 1346 insertions(+), 1391 deletions(-) delete mode 100644 usrp/host/include/usrp/usrp_basic.h create mode 100644 usrp/host/include/usrp/usrp_basic.h.in delete mode 100644 usrp/host/include/usrp/usrp_prims.h create mode 100644 usrp/host/include/usrp/usrp_prims.h.in diff --git a/config/usrp_fusb_tech.m4 b/config/usrp_fusb_tech.m4 index 196799e34..0be6a0ec5 100644 --- a/config/usrp_fusb_tech.m4 +++ b/config/usrp_fusb_tech.m4 @@ -29,9 +29,12 @@ AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ AC_HELP_STRING([--with-fusb-tech=OS], [Set fast USB technique (default=auto)]), [cf_with_fusb_tech="$withval"], - [cf_with_fusb_tech="$host_os"]) + [cf_with_fusb_tech="libusb1"]) if test [x]$1 != xno; then case "$cf_with_fusb_tech" in + libusb1*) + FUSB_TECH=libusb1 + ;; linux*) AC_CHECK_HEADER([linux/usbdevice_fs.h], [x_have_usbdevice_fs_h=yes], diff --git a/config/usrp_libusb.m4 b/config/usrp_libusb.m4 index cb3130c87..1d9cf0cbc 100644 --- a/config/usrp_libusb.m4 +++ b/config/usrp_libusb.m4 @@ -19,27 +19,78 @@ dnl Boston, MA 02110-1301, USA. AC_DEFUN([USRP_LIBUSB], [ libusbok=yes - PKG_CHECK_MODULES(USB, libusb, [], [ - AC_LANG_PUSH(C) + PKG_CHECK_MODULES(USB, libusb-1.0, [have_libusb1=yes; libusbok=yes], [ + PKG_CHECK_MODULES(USB, libusb, [have_libusb1=no; libusbok=yes], [libusbok=no]) + ]) - AC_CHECK_HEADERS([usb.h], [], [libusbok=no; AC_MSG_RESULT([USRP requires libusb. usb.h not found. See http://libusb.sf.net])]) + if test x$libusbok = xyes; then + if test x$have_libusb1 = xyes; then + AC_DEFINE(HAVE_LIBUSB_1, [1], [Define if libusb-1.0 found]) + fi + AC_OUTPUT_COMMANDS([ + case "$CONFIG_OTHER" in + usrp*) + outfile=usrp/host/include/usrp/$CONFIG_OTHER + tmpfile=${outfile}T + dirname="sed s,^.*/,,g" + + echo creating $outfile + cat > $tmpfile << _EOF_ +/* -*- Mode: C++ -*- +* -------------------------------------------------------------------- +* DO NOT EDIT THIS FILE! It has been automatically generated +* from: configure.in and `echo $outfile|$dirname`.in +* on host: `(hostname || uname -n) 2>/dev/null | sed 1q` +* -------------------------------------------------------------------- +*/ - save_LIBS="$LIBS" - case "$host_os" in - darwin*) - LIBS="$LIBS -lIOKit" +_EOF_ + echo "#ifndef _`echo $outfile | $dirname | tr a-z. A-Z_`_" >> $tmpfile + echo "#define _`echo $outfile | $dirname | tr a-z. A-Z_`_" >> $tmpfile + echo >> $tmpfile + + case "$CONFIG_OTHER" in + usrp_prims*) + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo >> $tmpfile ;; - *) ;; - esac + usrp_basic*) + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo '#include ' >> $tmpfile + echo >> $tmpfile + ;; + esac + + if test x$have_libusb1 = xno; then + echo 'struct usb_device;'>> $tmpfile + echo 'struct usb_dev_handle;'>> $tmpfile + echo 'typedef struct usb_device libusb_device;' >> $tmpfile + echo 'typedef struct usb_dev_handle libusb_device_handle;' >> $tmpfile + echo >> $tmpfile + fi - AC_SEARCH_LIBS(usb_bulk_write, [usb], [USB_LIBS="$LIBS"], [libusbok=no; AC_MSG_RESULT([USRP requires libusb. usb_bulk_write not found. See http://libusb.sf.net])]) + if test x$have_libusb1 = xyes; then + echo 'struct libusb_device;' >> $tmpfile + echo 'struct libusb_device_handle;' >> $tmpfile + echo >> $tmpfile + fi - LIBS="$save_LIBS" + # The ugly but portable cpp stuff comes from here + infile=usrp/host/include/usrp/`echo $outfile | sed 's,.*/,,g;s,\..*$,,g'`.h.in + sed '/^##.*$/d' $infile >> $tmpfile + mv ${tmpfile} ${outfile} + ;; + esac - AC_LANG_POP - ]) + ],[ + have_libusb1=$have_libusb1 + ]) - if test x$libusbok = xyes; then AC_SUBST(USB_LIBS) ifelse([$1], , :, [$1]) else diff --git a/usrp/host/Makefile.am b/usrp/host/Makefile.am index aa94fbd6e..cc4ba91aa 100644 --- a/usrp/host/Makefile.am +++ b/usrp/host/Makefile.am @@ -19,7 +19,7 @@ # Boston, MA 02110-1301, USA. # -SUBDIRS = misc lib include apps +SUBDIRS = misc include lib apps if PYTHON SUBDIRS += swig diff --git a/usrp/host/include/usrp/Makefile.am b/usrp/host/include/usrp/Makefile.am index d580d8a75..1e36b105a 100644 --- a/usrp/host/include/usrp/Makefile.am +++ b/usrp/host/include/usrp/Makefile.am @@ -23,6 +23,16 @@ include $(top_srcdir)/Makefile.common usrpincludedir = $(includedir)/usrp +usrp_prims.h: usrp_prims.h.in $(top_srcdir)/config.status + cd $(top_srcdir) \ + && CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=usrp_prims.h \ + $(SHELL) ./config.status + +usrp_basic.h: usrp_basic.h.in $(top_srcdir)/config.status + cd $(top_srcdir) \ + && CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=usrp_basic.h \ + $(SHELL) ./config.status + usrpinclude_HEADERS = \ db_base.h \ db_basic.h \ diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h deleted file mode 100644 index 3ec734113..000000000 --- a/usrp/host/include/usrp/usrp_basic.h +++ /dev/null @@ -1,1000 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,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. - */ - -/* - * ---------------------------------------------------------------------- - * 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. - * ---------------------------------------------------------------------- - */ - -#ifndef INCLUDED_USRP_BASIC_H -#define INCLUDED_USRP_BASIC_H - -#include -#include -#include -#include -#include -#include - -#if 1 -struct usb_dev_handle; -struct usb_device; -typedef struct usb_dev_handle libusb_device_handle; -typedef struct usb_device libusb_device; -#else -struct libusb_device_handle; -#endif - -class fusb_devhandle; -class fusb_ephandle; - -enum txrx_t { - C_RX = 0, - C_TX = 1 -}; - -/*! - * \brief abstract base class for usrp operations - * \ingroup usrp - */ -class usrp_basic : boost::noncopyable -{ -protected: - void shutdown_daughterboards(); - -protected: - libusb_device_handle *d_udh; - struct libusb_context *d_ctx; - int d_usb_data_rate; // bytes/sec - int d_bytes_per_poll; // how often to poll for overruns - bool d_verbose; - long d_fpga_master_clock_freq; - - static const int MAX_REGS = 128; - unsigned int d_fpga_shadows[MAX_REGS]; - - int d_dbid[2]; // daughterboard ID's (side A, side B) - - /*! - * Shared pointers to subclasses of db_base. - * - * The outer vector is of length 2 (0 = side A, 1 = side B). The - * inner vectors are of length 1, 2 or 3 depending on the number of - * subdevices implemented by the daugherboard. At this time, only - * the Basic Rx and LF Rx implement more than 1 subdevice. - */ - std::vector< std::vector > d_db; - - //! One time call, made only only from usrp_standard_*::make after shared_ptr is created. - void init_db(usrp_basic_sptr u); - - - usrp_basic (int which_board, - libusb_device_handle *open_interface (libusb_device *dev), - const std::string fpga_filename = "", - const std::string firmware_filename = ""); - - /*! - * \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 (); - - - /*! - * Return a vector of vectors that contain shared pointers - * to the daughterboard instance(s) associated with the specified side. - * - * It is an error to use the returned objects after the usrp_basic - * object has been destroyed. - */ - std::vector > db() const { return d_db; } - - /*! - * Return a vector of size >= 1 that contains shared pointers - * to the daughterboard instance(s) associated with the specified side. - * - * \param which_side [0,1] which daughterboard - * - * It is an error to use the returned objects after the usrp_basic - * object has been destroyed. - */ - std::vector db(int which_side); - - /*! - * \brief is the subdev_spec valid? - */ - bool is_valid(const usrp_subdev_spec &ss); - - /*! - * \brief given a subdev_spec, return the corresponding daughterboard object. - * \throws std::invalid_ argument if ss is invalid. - * - * \param ss specifies the side and subdevice - */ - db_base_sptr selected_subdev(const usrp_subdev_spec &ss); - - /*! - * \brief return frequency of master oscillator on USRP - */ - long fpga_master_clock_freq () const { return d_fpga_master_clock_freq; } - - /*! - * Tell API that the master oscillator on the USRP is operating at a non-standard - * fixed frequency. This is only needed for custom USRP hardware modified to - * operate at a different frequency from the default factory configuration. This - * function must be called prior to any other API function. - * \param master_clock USRP2 FPGA master clock frequency in Hz (10..64 MHz) - */ - void set_fpga_master_clock_freq (long master_clock) { d_fpga_master_clock_freq = master_clock; } - - /*! - * \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; } - - //! magic value used on alternate register read interfaces - static const int READ_FAILED = -99999; - - /*! - * \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 - * \returns the data read if successful, else a zero length string. - */ - std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); - - /*! - * \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 - * \returns the data read if successful, else a zero length string. - * Reads are limited to a maximum of 64 bytes. - */ - std::string read_i2c (int i2c_addr, int len); - - /*! - * \brief Set ADC offset correction - * \param which_adc 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_adc, int offset); - - /*! - * \brief Set DAC offset correction - * \param which_dac 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_dac, int offset, int offset_pin); - - /*! - * \brief Control ADC input buffer - * \param which_adc 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_adc, bool bypass); - - /*! - * \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. - * - *
-   * The 4 low bits are significant:
-   *
-   *   ADC0 = (1 << 0)
-   *   ADC1 = (1 << 1)
-   *   ADC2 = (1 << 2)
-   *   ADC3 = (1 << 3)
-   * 
- * - * By default the control loop is enabled on all ADC's. - */ - bool set_dc_offset_cl_enable(int bits, int mask); - - /*! - * \brief return the usrp's serial number. - * - * \returns non-zero length string iff successful. - */ - std::string serial_number(); - - /*! - * \brief Return daughterboard ID for given side [0,1]. - * - * \param which_side [0,1] which daughterboard - * - * \return daughterboard id >= 0 if successful - * \return -1 if no daugherboard - * \return -2 if invalid EEPROM on daughterboard - */ - virtual int daughterboard_id (int which_side) const = 0; - - /*! - * \brief Clock ticks to delay rising of T/R signal - * \sa write_atr_mask, write_atr_txval, write_atr_rxval - */ - bool write_atr_tx_delay(int value); - - /*! - * \brief Clock ticks to delay falling edge of T/R signal - * \sa write_atr_mask, write_atr_txval, write_atr_rxval - */ - bool write_atr_rx_delay(int value); - - - // ================================================================ - // Routines to access and control daughterboard specific i/o - // - // Those with a common_ prefix access either the Tx or Rx side depending - // on the txrx parameter. Those without the common_ prefix are virtual - // and are overriden in usrp_basic_rx and usrp_basic_tx to access the - // the Rx or Tx sides automatically. We provide the common_ versions - // for those daughterboards such as the WBX and XCVR2450 that share - // h/w resources (such as the LO) between the Tx and Rx sides. - - // ---------------------------------------------------------------- - // BEGIN common_ daughterboard control functions - - /*! - * \brief Set Programmable Gain Amplifier(PGA) - * - * \param txrx Tx or Rx? - * \param which_amp which amp [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 common_set_pga(txrx_t txrx, int which_amp, double gain_in_db); - - /*! - * \brief Return programmable gain amplifier gain setting in dB. - * - * \param txrx Tx or Rx? - * \param which_amp which amp [0,3] - */ - double common_pga(txrx_t txrx, int which_amp) const; - - /*! - * \brief Return minimum legal PGA gain in dB. - * \param txrx Tx or Rx? - */ - double common_pga_min(txrx_t txrx) const; - - /*! - * \brief Return maximum legal PGA gain in dB. - * \param txrx Tx or Rx? - */ - double common_pga_max(txrx_t txrx) const; - - /*! - * \brief Return hardware step size of PGA(linear in dB). - * \param txrx Tx or Rx? - */ - double common_pga_db_per_step(txrx_t txrx) const; - - /*! - * \brief Write direction register(output enables) for pins that go to daughterboard. - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which size - * \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 _common_write_oe(txrx_t txrx, int which_side, int value, int mask); - - /*! - * \brief Write daughterboard i/o pin value - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - */ - bool common_write_io(txrx_t txrx, int which_side, int value, int mask); - - /*! - * \brief Read daughterboard i/o pin value - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \param value output - */ - bool common_read_io(txrx_t txrx, int which_side, int *value); - - /*! - * \brief Read daughterboard i/o pin value - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \returns register value if successful, else READ_FAILED - */ - int common_read_io(txrx_t txrx, int which_side); - - /*! - * \brief Write daughterboard refclk config register - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \param value value to write into register, see below - * - *
-   * 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
-   * 
- */ - bool common_write_refclk(txrx_t txrx, int which_side, int value); - - /*! - * \brief 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.
-   * 
- */ - bool common_write_atr_mask(txrx_t txrx, int which_side, int value); - bool common_write_atr_txval(txrx_t txrx, int which_side, int value); - bool common_write_atr_rxval(txrx_t txrx, int which_side, int value); - - /*! - * \brief Write auxiliary digital to analog converter. - * - * \param txrx Tx or Rx? - * \param which_side [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 common_write_aux_dac(txrx_t txrx, int which_side, int which_dac, int value); - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \param which_adc [0,1] - * \param value return 12-bit value [0,4095] - * \returns true iff successful - */ - bool common_read_aux_adc(txrx_t txrx, int which_side, int which_adc, int *value); - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param txrx Tx or Rx? - * \param which_side [0,1] which d'board - * \param which_adc [0,1] - * \returns value in the range [0,4095] if successful, else READ_FAILED. - */ - int common_read_aux_adc(txrx_t txrx, int which_side, int which_adc); - - // END common_ daughterboard control functions - // ---------------------------------------------------------------- - // BEGIN virtual daughterboard control functions - - /*! - * \brief Set Programmable Gain Amplifier (PGA) - * - * \param which_amp which amp [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() - */ - virtual bool set_pga (int which_amp, double gain_in_db) = 0; - - /*! - * \brief Return programmable gain amplifier gain setting in dB. - * - * \param which_amp which amp [0,3] - */ - virtual double pga (int which_amp) const = 0; - - /*! - * \brief Return minimum legal PGA gain in dB. - */ - virtual double pga_min () const = 0; - - /*! - * \brief Return maximum legal PGA gain in dB. - */ - virtual double pga_max () const = 0; - - /*! - * \brief Return hardware step size of PGA (linear in dB). - */ - virtual double pga_db_per_step () const = 0; - - /*! - * \brief Write direction register (output enables) for pins that go to daughterboard. - * - * \param which_side [0,1] which size - * \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. - */ - virtual bool _write_oe (int which_side, int value, int mask) = 0; - - /*! - * \brief Write daughterboard i/o pin value - * - * \param which_side [0,1] which d'board - * \param value value to write into register - * \param mask which bits of value to write into reg - */ - virtual bool write_io (int which_side, int value, int mask) = 0; - - /*! - * \brief Read daughterboard i/o pin value - * - * \param which_side [0,1] which d'board - * \param value output - */ - virtual bool read_io (int which_side, int *value) = 0; - - /*! - * \brief Read daughterboard i/o pin value - * - * \param which_side [0,1] which d'board - * \returns register value if successful, else READ_FAILED - */ - virtual int read_io (int which_side) = 0; - - /*! - * \brief Write daughterboard refclk config register - * - * \param which_side [0,1] which d'board - * \param value value to write into register, see below - * - *
-   * 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
-   * 
- */ - virtual bool write_refclk(int which_side, int value) = 0; - - virtual bool write_atr_mask(int which_side, int value) = 0; - virtual bool write_atr_txval(int which_side, int value) = 0; - virtual bool write_atr_rxval(int which_side, int value) = 0; - - /*! - * \brief Write auxiliary digital to analog converter. - * - * \param which_side [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 - */ - virtual bool write_aux_dac (int which_side, int which_dac, int value) = 0; - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param which_side [0,1] which d'board - * \param which_adc [0,1] - * \param value return 12-bit value [0,4095] - * \returns true iff successful - */ - virtual bool read_aux_adc (int which_side, int which_adc, int *value) = 0; - - /*! - * \brief Read auxiliary analog to digital converter. - * - * \param which_side [0,1] which d'board - * \param which_adc [0,1] - * \returns value in the range [0,4095] if successful, else READ_FAILED. - */ - virtual int read_aux_adc (int which_side, int which_adc) = 0; - - /*! - * \brief returns current fusb block size - */ - virtual int block_size() const = 0; - - /*! - * \brief returns A/D or D/A converter rate in Hz - */ - virtual long converter_rate() const = 0; - - // END virtual daughterboard control functions - - // ---------------------------------------------------------------- - // Low level implementation routines. - // You probably shouldn't be using these... - // - - bool _set_led (int which_led, 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 FPGA register with mask. - * \param regno 7-bit register number - * \param value 16-bit value - * \param mask 16-bit value - * \returns true if successful - * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE - */ - bool _write_fpga_reg_masked (int regno, int value, int mask); - - /*! - * \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]. - * \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. - */ - std::string _read_spi (int optional_header, int enables, int format, int len); - - /*! - * \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 - * \ingroup 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: - /*! - * \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. - * \param fpga_filename name of the rbf file to load - * \param firmware_filename name of ihx file to load - */ - usrp_basic_rx (int which_board, - int fusb_block_size=0, - int fusb_nblocks=0, - const std::string fpga_filename = "", - const std::string firmware_filename = "" - ); // 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); - -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. - * \param fpga_filename name of file that contains image to load into FPGA - * \param firmware_filename name of file that contains image to load into FX2 - */ - static usrp_basic_rx *make (int which_board, - int fusb_block_size=0, - int fusb_nblocks=0, - const std::string fpga_filename = "", - const std::string firmware_filename = "" - ); - - /*! - * \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); - - - //! sampling rate of A/D converter - virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M - long adc_rate() const { return converter_rate(); } - int daughterboard_id (int which_side) const { return d_dbid[which_side & 0x1]; } - - bool set_pga (int which_amp, double gain_in_db); - double pga (int which_amp) const; - double pga_min () const; - double pga_max () const; - double pga_db_per_step () const; - - bool _write_oe (int which_side, int value, int mask); - bool write_io (int which_side, int value, int mask); - bool read_io (int which_side, int *value); - int read_io (int which_side); - bool write_refclk(int which_side, int value); - bool write_atr_mask(int which_side, int value); - bool write_atr_txval(int which_side, int value); - bool write_atr_rxval(int which_side, int value); - - bool write_aux_dac (int which_side, int which_dac, int value); - bool read_aux_adc (int which_side, int which_adc, int *value); - int read_aux_adc (int which_side, int which_adc); - - int block_size() const; - - // called in base class to derived class order - bool start (); - bool stop (); -}; - - /*! - * \brief class for accessing the transmit side of the USRP - * \ingroup usrp - */ -class usrp_basic_tx : 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_write; - bool d_tx_enable; - - protected: - /*! - * \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. - * \param fpga_filename name of file that contains image to load into FPGA - * \param firmware_filename name of file that contains image to load into FX2 - */ - usrp_basic_tx (int which_board, - int fusb_block_size=0, - int fusb_nblocks=0, - const std::string fpga_filename = "", - const std::string firmware_filename = "" - ); // 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); - -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. - * \param fpga_filename name of file that contains image to load into FPGA - * \param firmware_filename name of file that contains image to load into FX2 - */ - static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0, - const std::string fpga_filename = "", - const std::string firmware_filename = "" - ); - - /*! - * \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 (); - - //! 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(); } - int daughterboard_id (int which_side) const { return d_dbid[which_side & 0x1]; } - - bool set_pga (int which_amp, double gain_in_db); - double pga (int which_amp) const; - double pga_min () const; - double pga_max () const; - double pga_db_per_step () const; - - bool _write_oe (int which_side, int value, int mask); - bool write_io (int which_side, int value, int mask); - bool read_io (int which_side, int *value); - int read_io (int which_side); - bool write_refclk(int which_side, int value); - bool write_atr_mask(int which_side, int value); - bool write_atr_txval(int which_side, int value); - bool write_atr_rxval(int which_side, int value); - - bool write_aux_dac (int which_side, int which_dac, int value); - bool read_aux_adc (int which_side, int which_adc, int *value); - int read_aux_adc (int which_side, int which_adc); - - int block_size() const; - - // called in base class to derived class order - bool start (); - bool stop (); -}; - -#endif diff --git a/usrp/host/include/usrp/usrp_basic.h.in b/usrp/host/include/usrp/usrp_basic.h.in new file mode 100644 index 000000000..3faa5304f --- /dev/null +++ b/usrp/host/include/usrp/usrp_basic.h.in @@ -0,0 +1,960 @@ +class fusb_devhandle; +class fusb_ephandle; + +enum txrx_t { + C_RX = 0, + C_TX = 1 +}; + +/* + * ---------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------- + */ + + +/*! + * \brief abstract base class for usrp operations + * \ingroup usrp + */ +class usrp_basic : boost::noncopyable +{ +protected: + void shutdown_daughterboards(); + +protected: + libusb_device_handle *d_udh; + struct libusb_context *d_ctx; + int d_usb_data_rate; // bytes/sec + int d_bytes_per_poll; // how often to poll for overruns + bool d_verbose; + long d_fpga_master_clock_freq; + + static const int MAX_REGS = 128; + unsigned int d_fpga_shadows[MAX_REGS]; + + int d_dbid[2]; // daughterboard ID's (side A, side B) + + /*! + * Shared pointers to subclasses of db_base. + * + * The outer vector is of length 2 (0 = side A, 1 = side B). The + * inner vectors are of length 1, 2 or 3 depending on the number of + * subdevices implemented by the daugherboard. At this time, only + * the Basic Rx and LF Rx implement more than 1 subdevice. + */ + std::vector< std::vector > d_db; + + //! One time call, made only only from usrp_standard_*::make after shared_ptr is created. + void init_db(usrp_basic_sptr u); + + + usrp_basic (int which_board, + libusb_device_handle *open_interface (libusb_device *dev), + const std::string fpga_filename = "", + const std::string firmware_filename = ""); + + /*! + * \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 (); + + + /*! + * Return a vector of vectors that contain shared pointers + * to the daughterboard instance(s) associated with the specified side. + * + * It is an error to use the returned objects after the usrp_basic + * object has been destroyed. + */ + std::vector > db() const { return d_db; } + + /*! + * Return a vector of size >= 1 that contains shared pointers + * to the daughterboard instance(s) associated with the specified side. + * + * \param which_side [0,1] which daughterboard + * + * It is an error to use the returned objects after the usrp_basic + * object has been destroyed. + */ + std::vector db(int which_side); + + /*! + * \brief is the subdev_spec valid? + */ + bool is_valid(const usrp_subdev_spec &ss); + + /*! + * \brief given a subdev_spec, return the corresponding daughterboard object. + * \throws std::invalid_ argument if ss is invalid. + * + * \param ss specifies the side and subdevice + */ + db_base_sptr selected_subdev(const usrp_subdev_spec &ss); + + /*! + * \brief return frequency of master oscillator on USRP + */ + long fpga_master_clock_freq () const { return d_fpga_master_clock_freq; } + + /*! + * Tell API that the master oscillator on the USRP is operating at a non-standard + * fixed frequency. This is only needed for custom USRP hardware modified to + * operate at a different frequency from the default factory configuration. This + * function must be called prior to any other API function. + * \param master_clock USRP2 FPGA master clock frequency in Hz (10..64 MHz) + */ + void set_fpga_master_clock_freq (long master_clock) { d_fpga_master_clock_freq = master_clock; } + + /*! + * \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; } + + //! magic value used on alternate register read interfaces + static const int READ_FAILED = -99999; + + /*! + * \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 + * \returns the data read if successful, else a zero length string. + */ + std::string read_eeprom (int i2c_addr, int eeprom_offset, int len); + + /*! + * \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 + * \returns the data read if successful, else a zero length string. + * Reads are limited to a maximum of 64 bytes. + */ + std::string read_i2c (int i2c_addr, int len); + + /*! + * \brief Set ADC offset correction + * \param which_adc 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_adc, int offset); + + /*! + * \brief Set DAC offset correction + * \param which_dac 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_dac, int offset, int offset_pin); + + /*! + * \brief Control ADC input buffer + * \param which_adc 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_adc, bool bypass); + + /*! + * \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. + * + *
+   * The 4 low bits are significant:
+   *
+   *   ADC0 = (1 << 0)
+   *   ADC1 = (1 << 1)
+   *   ADC2 = (1 << 2)
+   *   ADC3 = (1 << 3)
+   * 
+ * + * By default the control loop is enabled on all ADC's. + */ + bool set_dc_offset_cl_enable(int bits, int mask); + + /*! + * \brief return the usrp's serial number. + * + * \returns non-zero length string iff successful. + */ + std::string serial_number(); + + /*! + * \brief Return daughterboard ID for given side [0,1]. + * + * \param which_side [0,1] which daughterboard + * + * \return daughterboard id >= 0 if successful + * \return -1 if no daugherboard + * \return -2 if invalid EEPROM on daughterboard + */ + virtual int daughterboard_id (int which_side) const = 0; + + /*! + * \brief Clock ticks to delay rising of T/R signal + * \sa write_atr_mask, write_atr_txval, write_atr_rxval + */ + bool write_atr_tx_delay(int value); + + /*! + * \brief Clock ticks to delay falling edge of T/R signal + * \sa write_atr_mask, write_atr_txval, write_atr_rxval + */ + bool write_atr_rx_delay(int value); + + + // ================================================================ + // Routines to access and control daughterboard specific i/o + // + // Those with a common_ prefix access either the Tx or Rx side depending + // on the txrx parameter. Those without the common_ prefix are virtual + // and are overriden in usrp_basic_rx and usrp_basic_tx to access the + // the Rx or Tx sides automatically. We provide the common_ versions + // for those daughterboards such as the WBX and XCVR2450 that share + // h/w resources (such as the LO) between the Tx and Rx sides. + + // ---------------------------------------------------------------- + // BEGIN common_ daughterboard control functions + + /*! + * \brief Set Programmable Gain Amplifier(PGA) + * + * \param txrx Tx or Rx? + * \param which_amp which amp [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 common_set_pga(txrx_t txrx, int which_amp, double gain_in_db); + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param txrx Tx or Rx? + * \param which_amp which amp [0,3] + */ + double common_pga(txrx_t txrx, int which_amp) const; + + /*! + * \brief Return minimum legal PGA gain in dB. + * \param txrx Tx or Rx? + */ + double common_pga_min(txrx_t txrx) const; + + /*! + * \brief Return maximum legal PGA gain in dB. + * \param txrx Tx or Rx? + */ + double common_pga_max(txrx_t txrx) const; + + /*! + * \brief Return hardware step size of PGA(linear in dB). + * \param txrx Tx or Rx? + */ + double common_pga_db_per_step(txrx_t txrx) const; + + /*! + * \brief Write direction register(output enables) for pins that go to daughterboard. + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which size + * \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 _common_write_oe(txrx_t txrx, int which_side, int value, int mask); + + /*! + * \brief Write daughterboard i/o pin value + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + bool common_write_io(txrx_t txrx, int which_side, int value, int mask); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \param value output + */ + bool common_read_io(txrx_t txrx, int which_side, int *value); + + /*! + * \brief Read daughterboard i/o pin value + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + int common_read_io(txrx_t txrx, int which_side); + + /*! + * \brief Write daughterboard refclk config register + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \param value value to write into register, see below + * + *
+   * 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
+   * 
+ */ + bool common_write_refclk(txrx_t txrx, int which_side, int value); + + /*! + * \brief 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.
+   * 
+ */ + bool common_write_atr_mask(txrx_t txrx, int which_side, int value); + bool common_write_atr_txval(txrx_t txrx, int which_side, int value); + bool common_write_atr_rxval(txrx_t txrx, int which_side, int value); + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param txrx Tx or Rx? + * \param which_side [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 common_write_aux_dac(txrx_t txrx, int which_side, int which_dac, int value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \param which_adc [0,1] + * \param value return 12-bit value [0,4095] + * \returns true iff successful + */ + bool common_read_aux_adc(txrx_t txrx, int which_side, int which_adc, int *value); + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param txrx Tx or Rx? + * \param which_side [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + int common_read_aux_adc(txrx_t txrx, int which_side, int which_adc); + + // END common_ daughterboard control functions + // ---------------------------------------------------------------- + // BEGIN virtual daughterboard control functions + + /*! + * \brief Set Programmable Gain Amplifier (PGA) + * + * \param which_amp which amp [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() + */ + virtual bool set_pga (int which_amp, double gain_in_db) = 0; + + /*! + * \brief Return programmable gain amplifier gain setting in dB. + * + * \param which_amp which amp [0,3] + */ + virtual double pga (int which_amp) const = 0; + + /*! + * \brief Return minimum legal PGA gain in dB. + */ + virtual double pga_min () const = 0; + + /*! + * \brief Return maximum legal PGA gain in dB. + */ + virtual double pga_max () const = 0; + + /*! + * \brief Return hardware step size of PGA (linear in dB). + */ + virtual double pga_db_per_step () const = 0; + + /*! + * \brief Write direction register (output enables) for pins that go to daughterboard. + * + * \param which_side [0,1] which size + * \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. + */ + virtual bool _write_oe (int which_side, int value, int mask) = 0; + + /*! + * \brief Write daughterboard i/o pin value + * + * \param which_side [0,1] which d'board + * \param value value to write into register + * \param mask which bits of value to write into reg + */ + virtual bool write_io (int which_side, int value, int mask) = 0; + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_side [0,1] which d'board + * \param value output + */ + virtual bool read_io (int which_side, int *value) = 0; + + /*! + * \brief Read daughterboard i/o pin value + * + * \param which_side [0,1] which d'board + * \returns register value if successful, else READ_FAILED + */ + virtual int read_io (int which_side) = 0; + + /*! + * \brief Write daughterboard refclk config register + * + * \param which_side [0,1] which d'board + * \param value value to write into register, see below + * + *
+   * 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
+   * 
+ */ + virtual bool write_refclk(int which_side, int value) = 0; + + virtual bool write_atr_mask(int which_side, int value) = 0; + virtual bool write_atr_txval(int which_side, int value) = 0; + virtual bool write_atr_rxval(int which_side, int value) = 0; + + /*! + * \brief Write auxiliary digital to analog converter. + * + * \param which_side [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 + */ + virtual bool write_aux_dac (int which_side, int which_dac, int value) = 0; + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_side [0,1] which d'board + * \param which_adc [0,1] + * \param value return 12-bit value [0,4095] + * \returns true iff successful + */ + virtual bool read_aux_adc (int which_side, int which_adc, int *value) = 0; + + /*! + * \brief Read auxiliary analog to digital converter. + * + * \param which_side [0,1] which d'board + * \param which_adc [0,1] + * \returns value in the range [0,4095] if successful, else READ_FAILED. + */ + virtual int read_aux_adc (int which_side, int which_adc) = 0; + + /*! + * \brief returns current fusb block size + */ + virtual int block_size() const = 0; + + /*! + * \brief returns A/D or D/A converter rate in Hz + */ + virtual long converter_rate() const = 0; + + // END virtual daughterboard control functions + + // ---------------------------------------------------------------- + // Low level implementation routines. + // You probably shouldn't be using these... + // + + bool _set_led (int which_led, 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 FPGA register with mask. + * \param regno 7-bit register number + * \param value 16-bit value + * \param mask 16-bit value + * \returns true if successful + * Only use this for registers who actually implement a mask in the verilog firmware, like FR_RX_MASTER_SLAVE + */ + bool _write_fpga_reg_masked (int regno, int value, int mask); + + /*! + * \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]. + * \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. + */ + std::string _read_spi (int optional_header, int enables, int format, int len); + + /*! + * \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 + * \ingroup 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: + /*! + * \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. + * \param fpga_filename name of the rbf file to load + * \param firmware_filename name of ihx file to load + */ + usrp_basic_rx (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // 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); + +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. + * \param fpga_filename name of file that contains image to load into FPGA + * \param firmware_filename name of file that contains image to load into FX2 + */ + static usrp_basic_rx *make (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + + /*! + * \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); + + + //! sampling rate of A/D converter + virtual long converter_rate() const { return fpga_master_clock_freq(); } // 64M + long adc_rate() const { return converter_rate(); } + int daughterboard_id (int which_side) const { return d_dbid[which_side & 0x1]; } + + bool set_pga (int which_amp, double gain_in_db); + double pga (int which_amp) const; + double pga_min () const; + double pga_max () const; + double pga_db_per_step () const; + + bool _write_oe (int which_side, int value, int mask); + bool write_io (int which_side, int value, int mask); + bool read_io (int which_side, int *value); + int read_io (int which_side); + bool write_refclk(int which_side, int value); + bool write_atr_mask(int which_side, int value); + bool write_atr_txval(int which_side, int value); + bool write_atr_rxval(int which_side, int value); + + bool write_aux_dac (int which_side, int which_dac, int value); + bool read_aux_adc (int which_side, int which_adc, int *value); + int read_aux_adc (int which_side, int which_adc); + + int block_size() const; + + // called in base class to derived class order + bool start (); + bool stop (); +}; + + /*! + * \brief class for accessing the transmit side of the USRP + * \ingroup usrp + */ +class usrp_basic_tx : 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_write; + bool d_tx_enable; + + protected: + /*! + * \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. + * \param fpga_filename name of file that contains image to load into FPGA + * \param firmware_filename name of file that contains image to load into FX2 + */ + usrp_basic_tx (int which_board, + int fusb_block_size=0, + int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); // 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); + +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. + * \param fpga_filename name of file that contains image to load into FPGA + * \param firmware_filename name of file that contains image to load into FX2 + */ + static usrp_basic_tx *make (int which_board, int fusb_block_size=0, int fusb_nblocks=0, + const std::string fpga_filename = "", + const std::string firmware_filename = "" + ); + + /*! + * \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 (); + + //! 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(); } + int daughterboard_id (int which_side) const { return d_dbid[which_side & 0x1]; } + + bool set_pga (int which_amp, double gain_in_db); + double pga (int which_amp) const; + double pga_min () const; + double pga_max () const; + double pga_db_per_step () const; + + bool _write_oe (int which_side, int value, int mask); + bool write_io (int which_side, int value, int mask); + bool read_io (int which_side, int *value); + int read_io (int which_side); + bool write_refclk(int which_side, int value); + bool write_atr_mask(int which_side, int value); + bool write_atr_txval(int which_side, int value); + bool write_atr_rxval(int which_side, int value); + + bool write_aux_dac (int which_side, int which_dac, int value); + bool read_aux_adc (int which_side, int which_adc, int *value); + int read_aux_adc (int which_side, int which_adc); + + int block_size() const; + + // called in base class to derived class order + bool start (); + bool stop (); +}; + +#endif diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h deleted file mode 100644 index bd7779b64..000000000 --- a/usrp/host/include/usrp/usrp_prims.h +++ /dev/null @@ -1,309 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2004,2006,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. - */ - -/* - * 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 - */ - -#ifndef _USRP_PRIMS_H_ -#define _USRP_PRIMS_H_ - -#include -#include - -static const int USRP_HASH_SIZE = 16; - -enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; - -#if 1 -struct usb_dev_handle; -struct usb_device; -typedef struct usb_dev_handle libusb_device_handle; -typedef struct usb_device libusb_device; -#else -struct libusb_device_handle; -struct libusb_device; -#endif - -struct libusb_context; - -/*! - * \brief initialize libusb; probe busses and devices. - * If new_context is set to true, initiate and returns new libusb_context. - * If new_context is set to false, intiate default context if not already - * initiated and return NULL. It is NOT safe to call more than once with - * new_context set to true since a new context is initiated each time. - */ -libusb_context* usrp_one_time_init (bool new_context); - -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) - */ -libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL); - -bool usrp_usrp_p (libusb_device *q); //< is this a USRP -bool usrp_usrp0_p (libusb_device *q); //< is this a USRP Rev 0 -bool usrp_usrp1_p (libusb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (libusb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (libusb_device *q); //< return h/w rev code - -bool usrp_fx2_p (libusb_device *q); //< is this an unconfigured Cypress FX2 - -bool usrp_unconfigured_usrp_p (libusb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (libusb_device *q); //< some kind of configured USRP - -/*! - * \brief given a libusb_device return an instance of the appropriate libusb_device_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. - */ -libusb_device_handle *usrp_open_cmd_interface (libusb_device *dev); -libusb_device_handle *usrp_open_rx_interface (libusb_device *dev); -libusb_device_handle *usrp_open_tx_interface (libusb_device *dev); - -/*! - * \brief close interface. - */ -bool usrp_close_interface (libusb_device_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 (libusb_device_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, libusb_context *ctx = NULL); - -/*! - * \brief load fpga configuration bitstream - */ -usrp_load_status_t -usrp_load_fpga (libusb_device_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, - const std::string fpga_filename = "", - const std::string firmware_filename = "", - libusb_context *ctx = NULL); - -/*! - * \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 (libusb_device_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 (libusb_device_handle *udh, int which, - unsigned char hash[USRP_HASH_SIZE]); - -bool usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value); -bool usrp_read_fpga_reg (libusb_device_handle *udh, int reg, int *value); -bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on); -bool usrp_set_led (libusb_device_handle *udh, int which, bool on); - -bool usrp_check_rx_overrun (libusb_device_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (libusb_device_handle *udh, bool *underrun_p); - -// i2c_read and i2c_write are limited to a maximum len of 64 bytes. - -bool usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, - const void *buf, int len); - -bool usrp_i2c_read (libusb_device_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 (libusb_device_handle *udh, - int optional_header, int enables, int format, - const void *buf, int len); - -bool usrp_spi_read (libusb_device_handle *udh, - int optional_header, int enables, int format, - void *buf, int len); - - -bool usrp_9862_write (libusb_device_handle *udh, - int which_codec, // [0, 1] - int regno, // [0, 63] - int value); // [0, 255] - -bool usrp_9862_read (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_handle *udh, int slot_id, - short offset0, short offset1); - -/*! - * \brief return a usrp's serial number. - * - * Note that this only works on a configured usrp. - * \returns non-zero length string iff successful. - */ -std::string usrp_serial_number(libusb_device_handle *udh); - -#endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in new file mode 100644 index 000000000..5e3df3389 --- /dev/null +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -0,0 +1,291 @@ +struct libusb_context; + +static const int USRP_HASH_SIZE = 16; + +enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; + +/*! + * \brief initialize libusb; probe busses and devices. + * If new_context is set to true, initiate and returns new libusb_context. + * If new_context is set to false, intiate default context if not already + * initiated and return NULL. It is NOT safe to call more than once with + * new_context set to true since a new context is initiated each time. + */ +libusb_context* usrp_one_time_init (bool new_context); + +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) + */ +libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL); + +bool usrp_usrp_p (libusb_device *q); //< is this a USRP +bool usrp_usrp0_p (libusb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (libusb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (libusb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (libusb_device *q); //< return h/w rev code + +bool usrp_fx2_p (libusb_device *q); //< is this an unconfigured Cypress FX2 + +bool usrp_unconfigured_usrp_p (libusb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (libusb_device *q); //< some kind of configured USRP + +/*! + * \brief given a libusb_device return an instance of the appropriate libusb_device_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. + */ +libusb_device_handle *usrp_open_cmd_interface (libusb_device *dev); +libusb_device_handle *usrp_open_rx_interface (libusb_device *dev); +libusb_device_handle *usrp_open_tx_interface (libusb_device *dev); + +/*! + * \brief close interface. + */ +bool usrp_close_interface (libusb_device_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 (libusb_device_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, libusb_context *ctx = NULL); + +/*! + * \brief load fpga configuration bitstream + */ +usrp_load_status_t +usrp_load_fpga (libusb_device_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, + const std::string fpga_filename = "", + const std::string firmware_filename = "", + libusb_context *ctx = NULL); + +/*! + * \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 (libusb_device_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 (libusb_device_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]); + +bool usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value); +bool usrp_read_fpga_reg (libusb_device_handle *udh, int reg, int *value); +bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on); +bool usrp_set_led (libusb_device_handle *udh, int which, bool on); + +bool usrp_check_rx_overrun (libusb_device_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (libusb_device_handle *udh, bool *underrun_p); + +// i2c_read and i2c_write are limited to a maximum len of 64 bytes. + +bool usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, + const void *buf, int len); + +bool usrp_i2c_read (libusb_device_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 (libusb_device_handle *udh, + int optional_header, int enables, int format, + const void *buf, int len); + +bool usrp_spi_read (libusb_device_handle *udh, + int optional_header, int enables, int format, + void *buf, int len); + + +bool usrp_9862_write (libusb_device_handle *udh, + int which_codec, // [0, 1] + int regno, // [0, 63] + int value); // [0, 255] + +bool usrp_9862_read (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_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 (libusb_device_handle *udh, int slot_id, + short offset0, short offset1); + +/*! + * \brief return a usrp's serial number. + * + * Note that this only works on a configured usrp. + * \returns non-zero length string iff successful. + */ +std::string usrp_serial_number(libusb_device_handle *udh); + +/* + * Static helper functions + */ + +bool _usrp_configured_p (libusb_device *q); +libusb_device_handle *usrp_open_interface(libusb_device *dev, + int interface, + int altinterface); +bool write_internal_ram (libusb_device_handle *udh, unsigned char *buf, + int start_addr, size_t len); +int write_cmd (libusb_device_handle *udh, int request, int value, + int index, unsigned char *bytes, int len); +bool usrp_usrp_p (libusb_device *q); +int usrp_hw_rev (libusb_device *q); +bool our_nanosleep (const struct timespec *delay); +const char *get_proto_filename (const std::string user_filename, + const char *env_var, + const char *def); +char *find_file (const char *filename, int hw_rev); +void load_status_msg (usrp_load_status_t s, const char *type, + const char *filename); +bool usrp1_fpga_write (libusb_device_handle *udh, int regno, int value); +bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value); +bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on); + +bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on); + +#endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 24d2bee6e..dbfda5a61 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -25,12 +25,15 @@ #ifndef _FUSB_H_ #define _FUSB_H_ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -#if 1 +#ifdef HAVE_LIBUSB_1 +struct libusb_device_handle; +#else struct usb_dev_handle; typedef struct usb_dev_handle libusb_device_handle; -#else -struct libusb_device_handle; #endif struct libusb_context; diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index 2579827e9..79e5b07ec 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -24,7 +24,7 @@ #include "config.h" #endif -#include +#include "usrp/usrp_basic.h" #include "usrp/usrp_prims.h" #include "usrp_interfaces.h" #include "fpga_regs_common.h" @@ -38,10 +38,10 @@ #include #include -#if 1 -#include -#else +#ifdef HAVE_LIBUSB_1 #include +#else +#include #endif using namespace ad9862; diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc index 296890b6c..c788cc054 100644 --- a/usrp/host/lib/usrp_basic_libusb.cc +++ b/usrp/host/lib/usrp_basic_libusb.cc @@ -39,7 +39,6 @@ #include #include - using namespace ad9862; #define NELEM(x) (sizeof (x) / sizeof (x[0])) diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index 4b695bec5..5ef6503d5 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -41,10 +41,10 @@ #include #include -#if 1 -#include -#else +#ifdef HAVE_LIBUSB_1 #include +#else +#include #endif extern "C" { @@ -66,18 +66,6 @@ static const int hash_slot_addr[2] = { static const char *default_firmware_filename = "std.ihx"; static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; -/* - * Forward Declarations - */ - -bool _usrp_configured_p (libusb_device *q); -libusb_device_handle *usrp_open_interface(libusb_device *dev, - int interface, - int altinterface); -bool write_internal_ram (libusb_device_handle *udh, unsigned char *buf, - int start_addr, size_t len); -int write_cmd (libusb_device_handle *udh, int request, int value, - int index, unsigned char *bytes, int len); #include "std_paths.h" #include diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc index 841d447ae..716e9fd70 100644 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -50,29 +50,6 @@ extern "C" { using namespace ad9862; -/* - * Forward Declarations - */ - -bool our_nanosleep (const struct timespec *delay); -const char *get_proto_filename (const std::string user_filename, - const char *env_var, - const char *def); -char *find_file (const char *filename, int hw_rev); -void load_status_msg (usrp_load_status_t s, const char *type, - const char *filename); -bool usrp1_fpga_write (libusb_device_handle *udh, int regno, int value); -bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value); -bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on); - -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); - - - static const int FIRMWARE_HASH_SLOT = 0; static const int FPGA_HASH_SLOT = 1; @@ -121,7 +98,7 @@ usrp_hw_rev (struct usb_device *q) /* * q must be a real USRP, not an FX2. Return true if it's configured. */ -static bool +bool _usrp_configured_p (struct usb_device *q) { return (q->descriptor.bcdDevice & 0xFF00) != 0; diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index 3f0763bf9..a99adafb3 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -50,24 +50,6 @@ extern "C" { using namespace ad9862; -bool our_nanosleep (const struct timespec *delay); -const char *get_proto_filename (const std::string user_filename, - const char *env_var, - const char *def); -char *find_file (const char *filename, int hw_rev); -void load_status_msg (usrp_load_status_t s, const char *type, - const char *filename); -bool usrp1_fpga_write (libusb_device_handle *udh, int regno, int value); -bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value); -bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on); - -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); - - static const int FIRMWARE_HASH_SLOT = 0; static const int FPGA_HASH_SLOT = 1; @@ -132,7 +114,7 @@ usrp_hw_rev (struct libusb_device *q) /* * q must be a real USRP, not an FX2. Return true if it's configured. */ -static bool +bool _usrp_configured_p (struct libusb_device *q) { struct libusb_device_descriptor desc; -- cgit