From b5aa407ec2b1bdebc1c950a9428789fe50327776 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Mon, 17 Aug 2009 23:46:30 -0400 Subject: Applied libusb-1.0 patch set from Thomas Tsou : This patch set updates the usrp to support libusb-1.0. Asynchronous I/O through libusb is added with fusb_libusb1.*, which is heavily based on fusb_linux.*. In short, URB's and ioctl calls are replaced with libusb_transfer structs and native calls. Transfer reaping is handled by libusb and associated callbacks. I get 32Mb/s on all of my machines using test_usrp_standard_rx or tx. Due to the API rewrite in 1.0 from 0.12, there are alot of changes, many are simply name changes. Known Issues: Transmit and receive both work, but not at same time (e.g. usrp_benchmark_usb.py). libusb does not create any internal threads, so for a single session fusb_libusb1 works in the same manner as fusb_linux with the callback called at controlled times. With multiple libusb sessions the callback may occur at any time and threading issues come into play causing behavior to become undefined. The use of separate libusb_contexts _might_ solve this issue; I have not had the time to look into it. --- usrp/host/apps/test_usrp_standard_rx.cc | 1 - usrp/host/apps/test_usrp_standard_tx.cc | 1 - usrp/host/apps/usrp_cal_dc_offset.cc | 1 - usrp/host/apps/usrper.cc | 6 +- usrp/host/include/usrp/usrp_basic.h | 20 +- usrp/host/include/usrp/usrp_prims.h | 90 ++--- usrp/host/lib/Makefile.am | 13 +- usrp/host/lib/fusb.cc | 2 +- usrp/host/lib/fusb.h | 10 +- usrp/host/lib/fusb_libusb1.cc | 679 ++++++++++++++++++++++++++++++++ usrp/host/lib/fusb_libusb1.h | 127 ++++++ usrp/host/lib/fusb_sysconfig_libusb1.cc | 49 +++ usrp/host/lib/usrp_basic.cc | 42 +- usrp/host/lib/usrp_prims.cc | 310 +++++++-------- usrp/host/swig/usrp_prims.i | 78 ++-- 15 files changed, 1135 insertions(+), 294 deletions(-) create mode 100644 usrp/host/lib/fusb_libusb1.cc create mode 100644 usrp/host/lib/fusb_libusb1.h create mode 100644 usrp/host/lib/fusb_sysconfig_libusb1.cc (limited to 'usrp/host') diff --git a/usrp/host/apps/test_usrp_standard_rx.cc b/usrp/host/apps/test_usrp_standard_rx.cc index f6897ed23..4098decda 100644 --- a/usrp/host/apps/test_usrp_standard_rx.cc +++ b/usrp/host/apps/test_usrp_standard_rx.cc @@ -28,7 +28,6 @@ #include #include #include -#include /* needed for usb functions */ #include #include #include diff --git a/usrp/host/apps/test_usrp_standard_tx.cc b/usrp/host/apps/test_usrp_standard_tx.cc index 3f8817373..cc9f9edfc 100644 --- a/usrp/host/apps/test_usrp_standard_tx.cc +++ b/usrp/host/apps/test_usrp_standard_tx.cc @@ -29,7 +29,6 @@ #include #include #include -#include /* needed for usb functions */ #include #include #include diff --git a/usrp/host/apps/usrp_cal_dc_offset.cc b/usrp/host/apps/usrp_cal_dc_offset.cc index 22d427dff..5f708d672 100644 --- a/usrp/host/apps/usrp_cal_dc_offset.cc +++ b/usrp/host/apps/usrp_cal_dc_offset.cc @@ -28,7 +28,6 @@ #include #include #include -#include /* needed for usb functions */ #include #include #include diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc index fe8ff90d2..1c4beb713 100644 --- a/usrp/host/apps/usrper.cc +++ b/usrp/host/apps/usrper.cc @@ -23,7 +23,7 @@ #include #include #include -#include /* needed for usb functions */ +#include /* needed for usb functions */ #include #include #include @@ -194,7 +194,7 @@ main (int argc, char **argv) usrp_one_time_init (); - struct usb_device *udev = usrp_find_device (which_board, fx2_ok_p); + struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p); if (udev == 0){ fprintf (stderr, "%s: failed to find usrp[%d]\n", prog_name, which_board); exit (1); @@ -208,7 +208,7 @@ main (int argc, char **argv) fprintf (stderr, "%s: found unconfigured FX2; needs firmware.\n", prog_name); } - struct usb_dev_handle *udh = usrp_open_cmd_interface (udev); + struct libusb_device_handle *udh = usrp_open_cmd_interface (udev); if (udh == 0){ fprintf (stderr, "%s: failed to open_cmd_interface\n", prog_name); exit (1); diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h index fbbf49d57..c79908a86 100644 --- a/usrp/host/include/usrp/usrp_basic.h +++ b/usrp/host/include/usrp/usrp_basic.h @@ -46,7 +46,7 @@ #include #include -struct usb_dev_handle; +struct libusb_device_handle; class fusb_devhandle; class fusb_ephandle; @@ -65,16 +65,16 @@ protected: void shutdown_daughterboards(); protected: - struct usb_dev_handle *d_udh; - 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; + struct libusb_device_handle *d_udh; + 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]; + static const int MAX_REGS = 128; + unsigned int d_fpga_shadows[MAX_REGS]; - int d_dbid[2]; // daughterboard ID's (side A, side B) + int d_dbid[2]; // daughterboard ID's (side A, side B) /*! * Shared pointers to subclasses of db_base. @@ -91,7 +91,7 @@ protected: usrp_basic (int which_board, - struct usb_dev_handle *open_interface (struct usb_device *dev), + struct libusb_device_handle *open_interface (struct libusb_device *dev), const std::string fpga_filename = "", const std::string firmware_filename = ""); diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h index aa0887050..df410b408 100644 --- a/usrp/host/include/usrp/usrp_prims.h +++ b/usrp/host/include/usrp/usrp_prims.h @@ -41,8 +41,8 @@ static const int USRP_HASH_SIZE = 16; enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; -struct usb_dev_handle; -struct usb_device; +struct libusb_device_handle; +struct libusb_device; /*! * \brief initialize libusb; probe busses and devices. @@ -65,21 +65,21 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false); +struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false); -bool usrp_usrp_p (struct usb_device *q); //< is this a USRP -bool usrp_usrp0_p (struct usb_device *q); //< is this a USRP Rev 0 -bool usrp_usrp1_p (struct usb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (struct usb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (struct usb_device *q); //< return h/w rev code +bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP +bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (struct libusb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (struct libusb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (struct libusb_device *q); //< return h/w rev code -bool usrp_fx2_p (struct usb_device *q); //< is this an unconfigured Cypress FX2 +bool usrp_fx2_p (struct libusb_device *q); //< is this an unconfigured Cypress FX2 -bool usrp_unconfigured_usrp_p (struct usb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured USRP +bool usrp_unconfigured_usrp_p (struct libusb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configured USRP /*! - * \brief given a usb_device return an instance of the appropriate usb_dev_handle + * \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!) @@ -87,14 +87,14 @@ bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured * If interface can't be opened, or is already claimed by some other * process, 0 is returned. */ -struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev); -struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev); -struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev); +struct libusb_device_handle *usrp_open_cmd_interface (struct libusb_device *dev); +struct libusb_device_handle *usrp_open_rx_interface (struct libusb_device *dev); +struct libusb_device_handle *usrp_open_tx_interface (struct libusb_device *dev); /*! * \brief close interface. */ -bool usrp_close_interface (struct usb_dev_handle *udh); +bool usrp_close_interface (struct libusb_device_handle *udh); /*! * \brief load intel hex format file into USRP/Cypress FX2 (8051). @@ -106,7 +106,7 @@ bool usrp_close_interface (struct usb_dev_handle *udh); */ usrp_load_status_t -usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force); +usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load intel hex format file into USRP FX2 (8051). @@ -125,7 +125,7 @@ usrp_load_firmware_nth (int nth, const char *filename, bool force); * \brief load fpga configuration bitstream */ usrp_load_status_t -usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force); +usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load the regular firmware and fpga bitstream in the Nth USRP. @@ -140,54 +140,54 @@ bool usrp_load_standard_bits (int nth, bool force, * \brief copy the given \p hash into the USRP hash slot \p which. * The usrp implements two hash slots, 0 and 1. */ -bool usrp_set_hash (struct usb_dev_handle *udh, int which, +bool usrp_set_hash (struct 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 (struct usb_dev_handle *udh, int which, +bool usrp_get_hash (struct libusb_device_handle *udh, int which, unsigned char hash[USRP_HASH_SIZE]); -bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value); -bool usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value); -bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on); +bool usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value); +bool usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value); +bool usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_led (struct libusb_device_handle *udh, int which, bool on); -bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p); +bool usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (struct 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 (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, const void *buf, int len); -bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_i2c_read (struct 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 (struct usb_dev_handle *udh, +bool usrp_spi_write (struct libusb_device_handle *udh, int optional_header, int enables, int format, const void *buf, int len); -bool usrp_spi_read (struct usb_dev_handle *udh, +bool usrp_spi_read (struct libusb_device_handle *udh, int optional_header, int enables, int format, void *buf, int len); -bool usrp_9862_write (struct usb_dev_handle *udh, +bool usrp_9862_write (struct libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] int value); // [0, 255] -bool usrp_9862_read (struct usb_dev_handle *udh, +bool usrp_9862_read (struct libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] unsigned char *value); // [0, 255] @@ -198,28 +198,28 @@ bool usrp_9862_read (struct usb_dev_handle *udh, * \p buf contains alternating register_number, register_value pairs. * \p len must be even and is the length of buf in bytes. */ -bool usrp_9862_write_many (struct usb_dev_handle *udh, int which_codec, +bool usrp_9862_write_many (struct 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 (struct usb_dev_handle *udh, +bool usrp_9862_write_many_all (struct 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 (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_eeprom_write (struct 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 (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, int eeprom_offset, void *buf, int len); @@ -241,7 +241,7 @@ bool usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, * binary values. Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit, * the interface is in terms of 12-bit values [0,4095] */ -bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot, +bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, int which_dac, int value); /*! @@ -251,7 +251,7 @@ bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot, * \p which_adc: [0,1] which of the two adcs to read * \p *value: return value, 12-bit straight binary. */ -bool usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, +bool usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, int which_adc, int *value); @@ -274,13 +274,13 @@ struct usrp_dboard_eeprom { * \brief Read and return parsed daughterboard eeprom */ usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct usb_dev_handle *udh, +usrp_read_dboard_eeprom (struct 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 (struct usb_dev_handle *udh, int slot_id, +bool usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, short offset0, short offset1); /*! @@ -289,6 +289,6 @@ bool usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id, * Note that this only works on a configured usrp. * \returns non-zero length string iff successful. */ -std::string usrp_serial_number(struct usb_dev_handle *udh); +std::string usrp_serial_number(struct libusb_device_handle *udh); #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 8e40692a5..e7c3f34c4 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -84,6 +84,9 @@ ra_wb_CODE = \ fusb_ra_wb.cc \ fusb_sysconfig_ra_wb.cc +libusb1_CODE = \ + fusb_libusb1.cc \ + fusb_sysconfig_libusb1.cc # # include each _CODE entry here... @@ -93,8 +96,8 @@ EXTRA_libusrp_la_SOURCES = \ $(darwin_CODE) \ $(win32_CODE) \ $(linux_CODE) \ - $(ra_wb_CODE) - + $(ra_wb_CODE) \ + $(libusb1_CODE) # work around automake deficiency libusrp_la_common_SOURCES = \ @@ -141,6 +144,11 @@ if FUSB_TECH_ra_wb libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(ra_wb_CODE) endif +if FUSB_TECH_libusb1 +libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(libusb1_CODE) +endif + + noinst_HEADERS = \ ad9862.h \ db_base_impl.h \ @@ -150,6 +158,7 @@ noinst_HEADERS = \ fusb_darwin.h \ fusb_generic.h \ fusb_linux.h \ + fusb_libusb1.h \ fusb_ra_wb.h \ fusb_win32.h \ md5.h \ diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc index 6e4358f5f..ce4bb7aa9 100644 --- a/usrp/host/lib/fusb.cc +++ b/usrp/host/lib/fusb.cc @@ -31,7 +31,7 @@ // device handle // ------------------------------------------------------------------------ -fusb_devhandle::fusb_devhandle (usb_dev_handle *udh) +fusb_devhandle::fusb_devhandle (libusb_device_handle *udh) : d_udh (udh) { // that's it diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 769e51cca..bfe34d5b8 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -26,7 +26,7 @@ #define _FUSB_H_ -struct usb_dev_handle; +struct libusb_device_handle; class fusb_ephandle; /*! @@ -39,11 +39,11 @@ private: fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator protected: - usb_dev_handle *d_udh; + libusb_device_handle *d_udh; public: // CREATORS - fusb_devhandle (usb_dev_handle *udh); + fusb_devhandle (libusb_device_handle *udh); virtual ~fusb_devhandle (); // MANIPULATORS @@ -55,7 +55,7 @@ public: int block_size = 0, int nblocks = 0) = 0; // ACCESSORS - usb_dev_handle *get_usb_dev_handle () const { return d_udh; } + libusb_device_handle *get_libusb_device_handle () const { return d_udh; } }; @@ -116,7 +116,7 @@ public: /*! * \brief returns fusb_devhandle or throws if trouble */ - static fusb_devhandle *make_devhandle (usb_dev_handle *udh); + static fusb_devhandle *make_devhandle (libusb_device_handle *udh); /*! * \brief Returns max block size in bytes (hard limit). diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc new file mode 100644 index 000000000..07e05c230 --- /dev/null +++ b/usrp/host/lib/fusb_libusb1.cc @@ -0,0 +1,679 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MINIMIZE_TX_BUFFERING true + +static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; +static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20); // 4 MB endpoint +static const int LIBUSB_TIMEOUT = 0; // no timeout + +inline static fusb_ephandle_libusb1* +lut_get_ephandle (libusb_transfer *lut) +{ + return (fusb_ephandle_libusb1 *) lut->user_data; +} + +// ------------------------------------------------------------------------ +// libusb_transfer allocation, deallocation, and callback +// ------------------------------------------------------------------------ + +static void +free_lut (libusb_transfer *lut) +{ + + // if this was an input transfer, free the buffer + if (lut->endpoint & 0x80) + delete [] ((unsigned char *) lut->buffer); + + libusb_free_transfer(lut); + +} + +/* + * The callback means the libusb_transfer is completed whether sent, cancelled, + * or failed. Move the libusb_transfer from the pending list to the + * completed list. If the cancel is from the destructor then free the + * transfer instead; normally this won't happen since all endpoints should be + * destroyed first leaving the pending list empty. + */ + +static void +generic_callback(struct libusb_transfer *lut) +{ + + // Fish out devhandle from endpoint + fusb_devhandle_libusb1* dev_handle = + lut_get_ephandle(lut)->get_fusb_devhandle_libusb1(); + + dev_handle->pending_remove(lut); + + if (lut->status == LIBUSB_TRANSFER_CANCELLED && dev_handle->_teardown() == 1) + { + free_lut (lut); + return; + } + + lut_get_ephandle(lut)->completed_list_add(lut); + +} + +static libusb_transfer* +alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, + bool input_p, unsigned char *write_buffer, + fusb_devhandle_libusb1 *dh) +{ + + struct libusb_transfer* lut = libusb_alloc_transfer(0); + + endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0); + + if (input_p) + write_buffer = new unsigned char [buffer_length]; + + // We need the base class libusb_device_handle + libusb_device_handle *dev_handle = dh->get_libusb_device_handle(); + + // Load the libusb_transfer for bulk transfer + libusb_fill_bulk_transfer (lut, // transfer + dev_handle, // dev_handle + endpoint, // endpoint + write_buffer, // buffer + buffer_length, // length + generic_callback, // callback + self, // user_data + LIBUSB_TIMEOUT); // timeout + + return lut; +} + +// ------------------------------------------------------------------------ +// device handle +// ------------------------------------------------------------------------ + +fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) + : fusb_devhandle (udh), d_teardown (false) +{ + // that's it +} + +fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () +{ + d_teardown = true; + + std::list::reverse_iterator it; + + // After cancellation the libusb_transfer is still active so delay freeing + // transfer until callback occurs. In most cases the pending list should + // already be empty by the time this destructor is called. + + for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++) { + _cancel_lut (*it); + } + + // Wait for pending list to empty + _wait_for_completion (); + +} + +fusb_ephandle* +fusb_devhandle_libusb1::make_ephandle (int endpoint, bool input_p, + int block_size, int nblocks) +{ + return new fusb_ephandle_libusb1 (this, endpoint, input_p, + block_size, nblocks); +} + +/* + * devhandle list manipulators + */ + +void +fusb_devhandle_libusb1::pending_add (libusb_transfer *lut) +{ + d_pending_rqsts.push_back (lut); +} + + +/* + * Attempt to cancel all transations associated with eph + */ + +void +fusb_devhandle_libusb1::_cancel_pending_rqsts (fusb_ephandle_libusb1 *eph) +{ + std::list::reverse_iterator it; + + for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){ + if (lut_get_ephandle (*it) == eph) + _cancel_lut (*it); + } +} + +/* + * Pull from the pending list + */ + +libusb_transfer * +fusb_devhandle_libusb1::pending_get () +{ + if (d_pending_rqsts.empty ()) + return 0; + + libusb_transfer *lut = d_pending_rqsts.front (); + d_pending_rqsts.pop_front (); + return lut; +} + +/* + * Match libusb_tranfer with the pending list and erase + * Return true if found, false otherwise + */ + +bool +fusb_devhandle_libusb1::pending_remove (libusb_transfer *lut) +{ + std::list::iterator result; + result = find (d_pending_rqsts.begin (), d_pending_rqsts.end (), lut); + + if (result == d_pending_rqsts.end ()) { + fprintf (stderr, "fusb::pending_remove: failed to find lut in pending_rqsts: %p\n", lut); + + return false; + } + d_pending_rqsts.erase (result); + return true; +} + +/* + * Submit the libusb_transfer to libusb + * iff successful, the transfer will be placed on the devhandle pending list. + */ + +bool +fusb_devhandle_libusb1::_submit_lut (libusb_transfer *lut) +{ + + int ret = libusb_submit_transfer (lut); + if (ret < 0) { + fprintf(stderr, "fusb::_submit_lut %d", ret); + return false; + } + + pending_add(lut); + return true; + +} + +/* + * Attempt to cancel any pending libusb_transfer transactions. + * Return true in the absence of errors, which does not mean that the transfer + * is cancelled. Cancellation can be checked after the callback is fired off + * by libusb. + */ + +bool +fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) +{ + + int ret = libusb_cancel_transfer (lut); + if (ret < 0) { + fprintf (stderr, "fusb::_cancel_lut"); + return false; + } + return true; + +} + +void +fusb_devhandle_libusb1::_wait_for_completion () +{ + + int ret; + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + + // The regular libusb_handle_events sets a hardcoded timeout of 2 + // seconds. Most of these calls should be changed to appropriate block / non- + // blocking version using libusb_handle_events_timeout. This was just a test + // usage. + + while (!d_pending_rqsts.empty ()) { + if ((ret = libusb_handle_events_timeout(NULL, &tv)) < 0) { + fprintf (stderr, "fusb: libusb_handle_events error %d\n", ret); + break; + } + } + +} + +// ------------------------------------------------------------------------ +// endpoint handle +// ------------------------------------------------------------------------ + +fusb_ephandle_libusb1::fusb_ephandle_libusb1 (fusb_devhandle_libusb1 *dh, + int endpoint, bool input_p, + int block_size, int nblocks) + : fusb_ephandle (endpoint, input_p, block_size, nblocks), + d_devhandle (dh), + d_write_work_in_progress (0), d_write_buffer (0), + d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0) +{ + + if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE) + throw std::out_of_range ("fusb_ephandle_libusb1: block_size"); + + if (d_nblocks < 0) + throw std::out_of_range ("fusb_ephandle_libusb1: nblocks"); + + if (d_block_size == 0) + d_block_size = DEFAULT_BLOCK_SIZE; + + if (d_nblocks == 0) + d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size); + + if (!d_input_p) + if (!MINIMIZE_TX_BUFFERING) + d_write_buffer = new unsigned char [d_block_size]; + + if (0) + fprintf(stderr, "fusb_ephandle_libusb1::ctor: d_block_size = %d d_nblocks = %d\n", + d_block_size, d_nblocks); + + // allocate libusb_transfers + for (int i = 0; i < d_nblocks; i++) + d_free_list.push_back (alloc_lut (this, d_block_size, d_endpoint, + d_input_p, d_write_buffer, d_devhandle)); +} + +fusb_ephandle_libusb1::~fusb_ephandle_libusb1 () +{ + + stop (); + + libusb_transfer *lut; + + while ((lut = free_list_get ()) != 0) + free_lut (lut); + + while ((lut = completed_list_get ()) != 0) + free_lut (lut); + + if (d_write_work_in_progress) + free_lut (d_write_work_in_progress); + + delete [] d_write_buffer; + + if (d_read_work_in_progress) + free_lut (d_read_work_in_progress); + +} + +bool +fusb_ephandle_libusb1::start () +{ + + if (d_started) + return true; + + d_started = true; + + if (d_input_p) { + libusb_transfer *lut; + + int nerrors = 0; + while ((lut = free_list_get ()) !=0 && nerrors < d_nblocks) { + if (!submit_lut (lut)) + nerrors++; + } + } + + return true; + +} + +/* + * Cancel all transfers in progress or pending and return to initial state + */ + +bool +fusb_ephandle_libusb1::stop () +{ + + if (!d_started) + return true; + + if (d_write_work_in_progress){ + free_list_add (d_write_work_in_progress); + d_write_work_in_progress = 0; + } + + if (d_read_work_in_progress){ + free_list_add (d_read_work_in_progress); + d_read_work_in_progress = 0; + d_read_buffer = 0; + d_read_buffer_end = 0; + } + + d_devhandle->_cancel_pending_rqsts (this); + + // Do work, reap transfers, etc. + if (libusb_handle_events(NULL) < 0) { + perror ("fusb::libusb_handle_events"); + return false; + } + + while (1) { + libusb_transfer *lut; + while ((lut = completed_list_get ()) != 0) + free_list_add (lut); + + if (d_free_list.size () == (unsigned) d_nblocks) + break; + + if (libusb_handle_events(NULL) < 0) { + perror ("fusb::libusb_handle_events"); + return false; + } + } + + d_started = false; + return true; + +} + +// ------------------------------------------------------------------------ +// routines for writing +// ------------------------------------------------------------------------ + +#if (MINIMIZE_TX_BUFFERING) + +int +fusb_ephandle_libusb1::write (const void *buffer, int nbytes) +{ + + if (!d_started) // doesn't matter here, but keeps semantics constant + return -1; + + if (d_input_p) + return -1; + + assert(nbytes % 512 == 0); + + unsigned char *src = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes){ + + struct libusb_transfer *lut = get_write_work_in_progress(); + if (!lut) + return -1; + assert(lut->actual_length == 0); + int m = std::min(nbytes - n, MAX_BLOCK_SIZE); + lut->buffer = src; + lut->length = m; + + n += m; + src += m; + + if (!submit_lut(lut)) + return -1; + + d_write_work_in_progress = 0; + } + + return nbytes; +} + +#else + +int +fusb_ephandle_libusb1::write (const void *buffer, int nbytes) +{ + if (!d_started) + return -1; + + if (d_input_p) + return -1; + + unsigned char *src = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes){ + + libusb_transfer *lut = get_write_work_in_progress (); + if (!lut) + return -1; + unsigned char *dst = (unsigned char *) lut->buffer; + int m = std::min (nbytes - n, lut->length - lut->actual_length); + + memcpy (&dst[lut->actual_length], &src[n], m); + lut->actual_length += m; + n += m; + + if (lut->actual_length == lut->length){ + if (!submit_lut (lut)) + return -1; + d_write_work_in_progress = 0; + } + } + + return n; +} + +#endif + +struct libusb_transfer * +fusb_ephandle_libusb1::get_write_work_in_progress () +{ + if (d_write_work_in_progress) + return d_write_work_in_progress; + + while (1) { + + reap_complete_writes (); + + struct libusb_transfer *lut = free_list_get (); + + if (lut != 0){ + assert (lut->actual_length == 0); + d_write_work_in_progress = lut; + return lut; + } + + // Do work, reap transfers, etc. + libusb_handle_events(NULL); + } +} + +void +fusb_ephandle_libusb1::reap_complete_writes () +{ + // take a look at the completed list and xfer to free list after + // checking for errors. + + libusb_transfer *lut; + + while ((lut = completed_list_get ()) != 0) { + + // Check for any errors or short writes that were reporetd in the transfer. + // libusb1 sets status, actual_length. + + if (lut->status != LIBUSB_TRANSFER_COMPLETED) { + fprintf (stderr, "fusb: (status %d) \n", lut->status ); + } + else if (lut->actual_length != lut->length){ + fprintf (stderr, "fusb: short write xfer: %d != %d\n", + lut->actual_length, lut->length); + } + + free_list_add (lut); + } +} + +void +fusb_ephandle_libusb1::wait_for_completion () +{ + d_devhandle->_wait_for_completion (); +} + +// ------------------------------------------------------------------------ +// routines for reading +// ------------------------------------------------------------------------ + +int +fusb_ephandle_libusb1::read (void *buffer, int nbytes) +{ + if (!d_started) // doesn't matter here, but keeps semantics constant + return -1; + + if (!d_input_p) + return -1; + + unsigned char *dst = (unsigned char *) buffer; + + int n = 0; + while (n < nbytes) { + + if (d_read_buffer >= d_read_buffer_end) + if (!reload_read_buffer ()) + return -1; + + int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer)); + + memcpy (&dst[n], d_read_buffer, m); + d_read_buffer += m; + n += m; + } + + return n; + +} + +bool +fusb_ephandle_libusb1::reload_read_buffer () +{ + assert (d_read_buffer >= d_read_buffer_end); + + libusb_transfer *lut; + + if (d_read_work_in_progress) { + lut = d_read_work_in_progress; + d_read_work_in_progress = 0; + d_read_buffer = 0; + d_read_buffer_end = 0; + lut->actual_length = 0; + if (!submit_lut (lut)) + return false; + } + + while (1) { + + while ((lut = completed_list_get ()) == 0 ) { + if (libusb_handle_events(NULL) < 0) + fprintf (stderr, "fusb: libusb_handle_events\n"); + } + + if (lut->status != LIBUSB_TRANSFER_COMPLETED) { + fprintf (stderr, "fust: (rd status %d) %s\n", lut->status, + strerror (-lut->status)); + lut->actual_length = 0; + free_list_add (lut); + return false; + } + + d_read_work_in_progress = lut; + d_read_buffer = (unsigned char *) lut->buffer; + d_read_buffer_end = d_read_buffer + lut->actual_length; + + return true; + } +} + + +/* + * ephandle list manipulation + */ + + +void +fusb_ephandle_libusb1::free_list_add (libusb_transfer *lut) +{ + assert (lut_get_ephandle (lut) == this); + lut->actual_length = 0; + d_free_list.push_back (lut); +} + +libusb_transfer * +fusb_ephandle_libusb1::free_list_get () +{ + if (d_free_list.empty ()) + return 0; + + libusb_transfer *lut = d_free_list.front (); + d_free_list.pop_front (); + return lut; +} + +void +fusb_ephandle_libusb1::completed_list_add (libusb_transfer *lut) +{ + assert (lut_get_ephandle (lut) == this); + d_completed_list.push_back (lut); +} + +libusb_transfer * +fusb_ephandle_libusb1::completed_list_get () +{ + if (d_completed_list.empty ()) + return 0; + + libusb_transfer *lut = d_completed_list.front (); + d_completed_list.pop_front (); + return lut; +} + +bool +fusb_ephandle_libusb1::submit_lut (libusb_transfer *lut) +{ + if (!d_devhandle->_submit_lut (lut)) { + fprintf (stderr, "_submit_lut failed\n"); + free_list_add (lut); + return false; + } + return true; +} diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h new file mode 100644 index 000000000..1661b7ab8 --- /dev/null +++ b/usrp/host/lib/fusb_libusb1.h @@ -0,0 +1,127 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _FUSB_LIBUSB1_H_ +#define _FUSB_LIBUSB1_H_ + +#include +#include + +struct libusb_transfer; +class fusb_ephandle_libusb1; + +/*! + * \brief libusb1 implementation of fusb_devhandle + */ +class fusb_devhandle_libusb1 : public fusb_devhandle +{ +private: + std::list d_pending_rqsts; + + void pending_add (struct libusb_transfer *lut); + struct libusb_transfer * pending_get (); + + bool d_teardown; + +public: + // CREATORS + fusb_devhandle_libusb1 (libusb_device_handle *udh); + virtual ~fusb_devhandle_libusb1 (); + + // MANIPULATORS + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + // internal use only + bool _submit_lut (libusb_transfer *); + bool _cancel_lut (libusb_transfer *); + void _cancel_pending_rqsts (fusb_ephandle_libusb1 *eph); + void _wait_for_completion (); + + // accessors to work from callback context + bool pending_remove (struct libusb_transfer *lut); + inline bool _teardown() { return d_teardown; } + +}; + + +/*! + * \brief libusb1 implementation of fusb_ephandle + */ +class fusb_ephandle_libusb1 : public fusb_ephandle +{ +private: + fusb_devhandle_libusb1 *d_devhandle; + std::list d_free_list; + std::list d_completed_list; + libusb_transfer *d_write_work_in_progress; + unsigned char *d_write_buffer; + libusb_transfer *d_read_work_in_progress; + unsigned char *d_read_buffer; + unsigned char *d_read_buffer_end; + + libusb_transfer *get_write_work_in_progress (); + void reap_complete_writes (); + bool reload_read_buffer (); + bool submit_lut (libusb_transfer *lut); + +public: + // CREATORS + fusb_ephandle_libusb1 (fusb_devhandle_libusb1 *dh, int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle_libusb1 (); + + // MANIPULATORS + + virtual bool start (); //!< begin streaming i/o + virtual bool stop (); //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes); + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes); + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion (); + + void free_list_add (struct libusb_transfer *lut); + void completed_list_add (struct libusb_transfer *lut); + struct libusb_transfer *free_list_get (); + struct libusb_transfer *completed_list_get (); + + // accessor to work from callback context + fusb_devhandle_libusb1* get_fusb_devhandle_libusb1 () const { + return d_devhandle; + } +}; + +#endif /* _FUSB_LINUX1_H_ */ + diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc new file mode 100644 index 000000000..e0d9458e1 --- /dev/null +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit +static const int DEFAULT_BLOCK_SIZE = 4 * 1024; +static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB + +fusb_devhandle * +fusb_sysconfig::make_devhandle (libusb_device_handle *udh) +{ + return new fusb_devhandle_libusb1 (udh); +} + +int fusb_sysconfig::max_block_size () +{ + return MAX_BLOCK_SIZE; +} + +int fusb_sysconfig::default_block_size () +{ + return DEFAULT_BLOCK_SIZE; +} + +int fusb_sysconfig::default_buffer_size () +{ + return FUSB_BUFFER_SIZE; +} diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc index 4f3df5212..a8b44edab 100644 --- a/usrp/host/lib/usrp_basic.cc +++ b/usrp/host/lib/usrp_basic.cc @@ -31,7 +31,7 @@ #include "fpga_regs_standard.h" #include "fusb.h" #include "db_boards.h" -#include +#include #include #include #include @@ -55,24 +55,22 @@ static const double POLLING_INTERVAL = 0.1; // seconds //////////////////////////////////////////////////////////////// -static struct usb_dev_handle * -open_rx_interface (struct usb_device *dev) +static struct libusb_device_handle * +open_rx_interface (struct libusb_device *dev) { - struct usb_dev_handle *udh = usrp_open_rx_interface (dev); + struct libusb_device_handle *udh = usrp_open_rx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); - usb_strerror (); } return udh; } -static struct usb_dev_handle * -open_tx_interface (struct usb_device *dev) +static struct libusb_device_handle * +open_tx_interface (struct libusb_device *dev) { - struct usb_dev_handle *udh = usrp_open_tx_interface (dev); + struct libusb_device_handle *udh = usrp_open_tx_interface (dev); if (udh == 0){ fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); - usb_strerror (); } return udh; } @@ -106,8 +104,8 @@ static unsigned char common_regs[] = { usrp_basic::usrp_basic (int which_board, - struct usb_dev_handle * - open_interface (struct usb_device *dev), + struct libusb_device_handle * + open_interface (struct libusb_device *dev), const std::string fpga_filename, const std::string firmware_filename) : d_udh (0), @@ -132,7 +130,7 @@ usrp_basic::usrp_basic (int which_board, if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); - struct usb_device *dev = usrp_find_device (which_board); + struct libusb_device *dev = usrp_find_device (which_board); if (dev == 0){ fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); throw std::runtime_error ("usrp_basic/usrp_find_device"); @@ -175,7 +173,14 @@ usrp_basic::~usrp_basic () d_db.resize(0); // forget db shared ptrs if (d_udh) - usb_close (d_udh); + libusb_close (d_udh); + + // There's no reference count on the number of times libusb is initialized. + // libusb_init can be called multiple times, but libusb_exit shuts down + // everything. Leave libusb running for now. Need to add a count so that it + // exits nicely. + + //libusb_exit (NULL); } void @@ -834,7 +839,6 @@ usrp_basic_rx::~usrp_basic_rx () { if (!set_rx_enable (false)){ fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n"); - usb_strerror (); } d_ephandle->stop (); @@ -859,13 +863,11 @@ usrp_basic_rx::start () if (!d_ephandle->start ()){ fprintf (stderr, "usrp_basic_rx: failed to start end point streaming"); - usb_strerror (); return false; } if (!set_rx_enable (true)){ fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); - usb_strerror (); return false; } @@ -879,13 +881,11 @@ usrp_basic_rx::stop () if (!set_rx_enable(false)){ fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n"); - usb_strerror (); ok = false; } if (!d_ephandle->stop()){ fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming"); - usb_strerror (); ok = false; } @@ -959,7 +959,6 @@ usrp_basic_rx::read (void *buf, int len, bool *overrun) d_bytes_seen = 0; if (!usrp_check_rx_overrun (d_udh, overrun)){ fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n"); - usb_strerror (); } } @@ -1264,13 +1263,11 @@ usrp_basic_tx::start () if (!set_tx_enable (true)){ fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); - usb_strerror (); return false; } if (!d_ephandle->start ()){ fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); - usb_strerror (); return false; } @@ -1284,13 +1281,11 @@ usrp_basic_tx::stop () if (!d_ephandle->stop ()){ fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming"); - usb_strerror (); ok = false; } if (!set_tx_enable (false)){ fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n"); - usb_strerror (); ok = false; } @@ -1364,7 +1359,6 @@ usrp_basic_tx::write (const void *buf, int len, bool *underrun) d_bytes_seen = 0; if (!usrp_check_tx_underrun (d_udh, underrun)){ fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n"); - usb_strerror (); } } diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc index 3d87d2459..e1e3e3074 100644 --- a/usrp/host/lib/usrp_prims.cc +++ b/usrp/host/lib/usrp_prims.cc @@ -30,7 +30,7 @@ #include "usrp_i2c_addr.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" -#include +#include #include #include #include @@ -101,7 +101,7 @@ get_proto_filename(const std::string user_filename, const char *env_var, const c } -static void power_down_9862s (struct usb_dev_handle *udh); +static void power_down_9862s (struct libusb_device_handle *udh); void usrp_one_time_init () @@ -110,35 +110,14 @@ usrp_one_time_init () if (first){ first = false; - usb_init (); // usb library init - usb_find_busses (); - usb_find_devices (); + libusb_init (NULL); // usb library init } } void usrp_rescan () { - usb_find_busses (); - usb_find_devices (); -} - - -// ---------------------------------------------------------------- -// Danger, big, fragile KLUDGE. The problem is that we want to be -// able to get from a usb_dev_handle back to a usb_device, and the -// right way to do this is buried in a non-installed include file. - -static struct usb_device * -dev_handle_to_dev (usb_dev_handle *udh) -{ - struct usb_dev_handle_kludge { - int fd; - struct usb_bus *bus; - struct usb_device *device; - }; - - return ((struct usb_dev_handle_kludge *) udh)->device; + // deprecated? } // ---------------------------------------------------------------- @@ -147,171 +126,176 @@ dev_handle_to_dev (usb_dev_handle *udh) * q must be a real USRP, not an FX2. Return its hardware rev number. */ int -usrp_hw_rev (struct usb_device *q) +usrp_hw_rev (struct libusb_device *q) { - return q->descriptor.bcdDevice & 0x00FF; + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return desc.bcdDevice & 0x00FF; } /* * q must be a real USRP, not an FX2. Return true if it's configured. */ static bool -_usrp_configured_p (struct usb_device *q) +_usrp_configured_p (struct libusb_device *q) { - return (q->descriptor.bcdDevice & 0xFF00) != 0; + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.bcdDevice & 0xFF00) != 0; } bool -usrp_usrp_p (struct usb_device *q) +usrp_usrp_p (struct libusb_device *q) { - return (q->descriptor.idVendor == USB_VID_FSF - && q->descriptor.idProduct == USB_PID_FSF_USRP); + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.idVendor == USB_VID_FSF + && desc.idProduct == USB_PID_FSF_USRP); } bool -usrp_fx2_p (struct usb_device *q) +usrp_fx2_p (struct libusb_device *q) { - return (q->descriptor.idVendor == USB_VID_CYPRESS - && q->descriptor.idProduct == USB_PID_CYPRESS_FX2); + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.idVendor == USB_VID_CYPRESS + && desc.idProduct == USB_PID_CYPRESS_FX2); } bool -usrp_usrp0_p (struct usb_device *q) +usrp_usrp0_p (struct libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 0; } bool -usrp_usrp1_p (struct usb_device *q) +usrp_usrp1_p (struct libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 1; } bool -usrp_usrp2_p (struct usb_device *q) +usrp_usrp2_p (struct libusb_device *q) { return usrp_usrp_p (q) && usrp_hw_rev (q) == 2; } bool -usrp_unconfigured_usrp_p (struct usb_device *q) +usrp_unconfigured_usrp_p (struct libusb_device *q) { return usrp_usrp_p (q) && !_usrp_configured_p (q); } bool -usrp_configured_usrp_p (struct usb_device *q) +usrp_configured_usrp_p (struct libusb_device *q) { return usrp_usrp_p (q) && _usrp_configured_p (q); } // ---------------------------------------------------------------- -struct usb_device * +struct libusb_device * usrp_find_device (int nth, bool fx2_ok_p) { - struct usb_bus *p; - struct usb_device *q; + libusb_device **list; + + struct libusb_device *q; int n_found = 0; usrp_one_time_init (); - - p = usb_get_busses(); - while (p != NULL){ - q = p->devices; - while (q != NULL){ - if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ + + size_t cnt = libusb_get_device_list(NULL, &list); + size_t i = 0; + + if (cnt < 0) + fprintf(stderr, "usrp: libusb_get_device_list failed %d\n", cnt); + + for (i = 0; i < cnt; i++) { + q = list[i]; + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) { if (n_found == nth) // return this one return q; n_found++; // keep looking - } - q = q->next; } - p = p->next; } + + libusb_free_device_list(list, 1); return 0; // not found } -static struct usb_dev_handle * -usrp_open_interface (struct usb_device *dev, int interface, int altinterface) +static struct libusb_device_handle * +usrp_open_interface (struct libusb_device *dev, int interface, int altinterface) { - struct usb_dev_handle *udh = usb_open (dev); - if (udh == 0) + struct libusb_device_handle *udh; + int ret; + + if (libusb_open (dev, &udh) < 0) return 0; - if (dev != dev_handle_to_dev (udh)){ + if (dev != libusb_get_device (udh)){ fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); abort (); } -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) - // There's no get get_configuration function, and with some of the newer kernels - // setting the configuration, even if to the same value, hoses any other processes - // that have it open. Hence we opt to not set it at all (We've only - // got a single configuration anyway). This may hose the win32 stuff... - - // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 - if (usb_set_configuration (udh, 1) < 0){ - /* - * Ignore this error. - * - * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that - * it returns -EBUSY if _any_ of the interfaces of a device are open. - * We've only got a single configuration, so setting it doesn't even seem - * like it should be required. - */ - } -#endif - - if (usb_claim_interface (udh, interface) < 0){ + if ((ret = libusb_claim_interface (udh, interface)) < 0) { fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); - fprintf (stderr, "%s\n", usb_strerror()); - usb_close (udh); + fprintf (stderr, "%d\n", ret); + libusb_close (udh); return 0; } - if (usb_set_altinterface (udh, altinterface) < 0){ + if ((ret = libusb_set_interface_alt_setting (udh, interface, + altinterface)) < 0) { fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); - fprintf (stderr, "%s\n", usb_strerror()); - usb_release_interface (udh, interface); - usb_close (udh); + fprintf (stderr, "%d\n", ret); + libusb_release_interface (udh, interface); + libusb_close (udh); return 0; } return udh; } -struct usb_dev_handle * -usrp_open_cmd_interface (struct usb_device *dev) +struct libusb_device_handle * +usrp_open_cmd_interface (struct libusb_device *dev) { return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE); } -struct usb_dev_handle * -usrp_open_rx_interface (struct usb_device *dev) +struct libusb_device_handle * +usrp_open_rx_interface (struct libusb_device *dev) { return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE); } -struct usb_dev_handle * -usrp_open_tx_interface (struct usb_device *dev) +struct libusb_device_handle * +usrp_open_tx_interface (struct libusb_device *dev) { return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE); } bool -usrp_close_interface (struct usb_dev_handle *udh) +usrp_close_interface (struct libusb_device_handle *udh) { - // we're assuming that closing an interface automatically releases it. - return usb_close (udh) == 0; + // returns void + libusb_close(udh); + return 0; } // ---------------------------------------------------------------- // write internal ram using Cypress vendor extension static bool -write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, +write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf, int start_addr, size_t len) { int addr; @@ -324,11 +308,11 @@ write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, if (n > quanta) n = quanta; - a = usb_control_msg (udh, 0x40, 0xA0, - addr, 0, (char *)(buf + (addr - start_addr)), n, 1000); + a = libusb_control_transfer (udh, 0x40, 0xA0, + addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror()); + fprintf(stderr,"write_internal_ram failed: %u\n", a); return false; } } @@ -339,7 +323,7 @@ write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, // whack the CPUCS register using the upload RAM vendor extension static bool -reset_cpu (struct usb_dev_handle *udh, bool reset_p) +reset_cpu (struct libusb_device_handle *udh, bool reset_p) { unsigned char v; @@ -355,7 +339,7 @@ reset_cpu (struct usb_dev_handle *udh, bool reset_p) // Load intel format file into cypress FX2 (8051) static bool -_usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, +_usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, unsigned char hash[USRP_HASH_SIZE]) { FILE *f = fopen (filename, "ra"); @@ -437,18 +421,20 @@ _usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, // write vendor extension command to USRP static int -write_cmd (struct usb_dev_handle *udh, +write_cmd (struct libusb_device_handle *udh, int request, int value, int index, unsigned char *bytes, int len) { int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; - int r = usb_control_msg (udh, requesttype, request, value, index, - (char *) bytes, len, 1000); + int r = libusb_control_transfer(udh, requesttype, request, value, index, + (unsigned char *) bytes, len, 1000); + if (r < 0){ // we get EPIPE if the firmware stalls the endpoint. - if (errno != EPIPE) - fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ()); + if (r != LIBUSB_ERROR_PIPE) { + fprintf (stderr, "libusb_control_transfer failed: %i\n", r); + } } return r; @@ -458,7 +444,7 @@ write_cmd (struct usb_dev_handle *udh, // load fpga static bool -_usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, +_usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, unsigned char hash[USRP_HASH_SIZE]) { bool ok = true; @@ -536,7 +522,7 @@ _usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, // ---------------------------------------------------------------- bool -usrp_set_led (struct usb_dev_handle *udh, int which, bool on) +usrp_set_led (struct libusb_device_handle *udh, int which, bool on) { int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); @@ -544,38 +530,38 @@ usrp_set_led (struct usb_dev_handle *udh, int which, bool on) } bool -usrp_set_hash (struct usb_dev_handle *udh, int which, +usrp_set_hash (struct libusb_device_handle *udh, int which, const unsigned char hash[USRP_HASH_SIZE]) { which &= 1; // we use the Cypress firmware down load command to jam it in. - int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (char *) hash, USRP_HASH_SIZE, 1000); + int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } bool -usrp_get_hash (struct usb_dev_handle *udh, int which, +usrp_get_hash (struct libusb_device_handle *udh, int which, unsigned char hash[USRP_HASH_SIZE]) { which &= 1; // we use the Cypress firmware upload command to fetch it. - int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (char *) hash, USRP_HASH_SIZE, 1000); + int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } static bool -usrp_set_switch (struct usb_dev_handle *udh, int cmd_byte, bool on) +usrp_set_switch (struct libusb_device_handle *udh, int cmd_byte, bool on) { return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; } static bool -usrp1_fpga_write (struct usb_dev_handle *udh, +usrp1_fpga_write (struct libusb_device_handle *udh, int regno, int value) { // on the rev1 usrp, we use the generic spi_write interface @@ -594,7 +580,7 @@ usrp1_fpga_write (struct usb_dev_handle *udh, } static bool -usrp1_fpga_read (struct usb_dev_handle *udh, +usrp1_fpga_read (struct libusb_device_handle *udh, int regno, int *value) { *value = 0; @@ -613,9 +599,9 @@ usrp1_fpga_read (struct usb_dev_handle *udh, bool -usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) +usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value) { - switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + switch (usrp_hw_rev (libusb_get_device (udh))){ case 0: // not supported ;) abort(); @@ -625,9 +611,9 @@ usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) } bool -usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) +usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) { - switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + switch (usrp_hw_rev (libusb_get_device (udh))){ case 0: // not supported ;) abort(); @@ -637,31 +623,31 @@ usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) } bool -usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on) +usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); } bool -usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on) +usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); } bool -usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on) +usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); } bool -usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on) +usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); } bool -usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on) +usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); } @@ -688,11 +674,11 @@ compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) } static usrp_load_status_t -usrp_conditionally_load_something (struct usb_dev_handle *udh, +usrp_conditionally_load_something (struct libusb_device_handle *udh, const char *filename, bool force, int slot, - bool loader (struct usb_dev_handle *, + bool loader (struct libusb_device_handle *, const char *, unsigned char [USRP_HASH_SIZE])) { @@ -721,7 +707,7 @@ usrp_conditionally_load_something (struct usb_dev_handle *udh, } usrp_load_status_t -usrp_load_firmware (struct usb_dev_handle *udh, +usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force) { @@ -731,7 +717,7 @@ usrp_load_firmware (struct usb_dev_handle *udh, } usrp_load_status_t -usrp_load_fpga (struct usb_dev_handle *udh, +usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool force) { @@ -740,23 +726,22 @@ usrp_load_fpga (struct usb_dev_handle *udh, _usrp_load_fpga); } -static usb_dev_handle * +static libusb_device_handle * open_nth_cmd_interface (int nth) { - struct usb_device *udev = usrp_find_device (nth); + struct libusb_device *udev = usrp_find_device (nth); if (udev == 0){ fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); return 0; } - struct usb_dev_handle *udh; + struct libusb_device_handle *udh; udh = usrp_open_cmd_interface (udev); if (udh == 0){ // FIXME this could be because somebody else has it open. // We should delay and retry... fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); - usb_strerror (); return 0; } @@ -793,7 +778,7 @@ mdelay (int millisecs) usrp_load_status_t usrp_load_firmware_nth (int nth, const char *filename, bool force){ - struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + struct libusb_device_handle *udh = open_nth_cmd_interface (nth); if (udh == 0) return ULS_ERROR; @@ -820,9 +805,6 @@ usrp_load_firmware_nth (int nth, const char *filename, bool force){ t.tv_nsec = 0; our_nanosleep (&t); - usb_find_busses (); // rescan busses and devices - usb_find_devices (); - return ULS_OK; default: @@ -866,7 +848,7 @@ usrp_load_standard_bits (int nth, bool force, // first, figure out what hardware rev we're dealing with { - struct usb_device *udev = usrp_find_device (nth); + struct libusb_device *udev = usrp_find_device (nth); if (udev == 0){ fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); return false; @@ -904,7 +886,7 @@ usrp_load_standard_bits (int nth, bool force, return false; } - struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + struct libusb_device_handle *udh = open_nth_cmd_interface (nth); if (udh == 0) return false; @@ -919,7 +901,7 @@ usrp_load_standard_bits (int nth, bool force, } bool -_usrp_get_status (struct usb_dev_handle *udh, int which, bool *trouble) +_usrp_get_status (struct libusb_device_handle *udh, int which, bool *trouble) { unsigned char status; *trouble = true; @@ -933,20 +915,20 @@ _usrp_get_status (struct usb_dev_handle *udh, int which, bool *trouble) } bool -usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p) +usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p) { return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p); } bool -usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p) +usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p) { return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p); } bool -usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr, +usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, const void *buf, int len) { if (len < 1 || len > MAX_EP0_PKTSIZE) @@ -958,7 +940,7 @@ usrp_i2c_write (struct usb_dev_handle *udh, int i2c_addr, bool -usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, +usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, void *buf, int len) { if (len < 1 || len > MAX_EP0_PKTSIZE) @@ -969,7 +951,7 @@ usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, } bool -usrp_spi_write (struct usb_dev_handle *udh, +usrp_spi_write (struct libusb_device_handle *udh, int optional_header, int enables, int format, const void *buf, int len) { @@ -984,7 +966,7 @@ usrp_spi_write (struct usb_dev_handle *udh, bool -usrp_spi_read (struct usb_dev_handle *udh, +usrp_spi_read (struct libusb_device_handle *udh, int optional_header, int enables, int format, void *buf, int len) { @@ -998,7 +980,7 @@ usrp_spi_read (struct usb_dev_handle *udh, } bool -usrp_9862_write (struct usb_dev_handle *udh, int which_codec, +usrp_9862_write (struct libusb_device_handle *udh, int which_codec, int regno, int value) { if (0) @@ -1016,7 +998,7 @@ usrp_9862_write (struct usb_dev_handle *udh, int which_codec, } bool -usrp_9862_read (struct usb_dev_handle *udh, int which_codec, +usrp_9862_read (struct libusb_device_handle *udh, int which_codec, int regno, unsigned char *value) { return usrp_spi_read (udh, 0x80 | (regno & 0x3f), @@ -1026,7 +1008,7 @@ usrp_9862_read (struct usb_dev_handle *udh, int which_codec, } bool -usrp_9862_write_many (struct usb_dev_handle *udh, +usrp_9862_write_many (struct libusb_device_handle *udh, int which_codec, const unsigned char *buf, int len) @@ -1047,7 +1029,7 @@ usrp_9862_write_many (struct usb_dev_handle *udh, bool -usrp_9862_write_many_all (struct usb_dev_handle *udh, +usrp_9862_write_many_all (struct libusb_device_handle *udh, const unsigned char *buf, int len) { // FIXME handle 2/2 and 4/4 versions @@ -1059,7 +1041,7 @@ usrp_9862_write_many_all (struct usb_dev_handle *udh, } static void -power_down_9862s (struct usb_dev_handle *udh) +power_down_9862s (struct libusb_device_handle *udh) { static const unsigned char regs[] = { REG_RX_PWR_DN, 0x01, // everything @@ -1067,7 +1049,7 @@ power_down_9862s (struct usb_dev_handle *udh) REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled }; - switch (usrp_hw_rev (dev_handle_to_dev (udh))){ + switch (usrp_hw_rev (libusb_get_device (udh))){ case 0: break; @@ -1082,7 +1064,7 @@ power_down_9862s (struct usb_dev_handle *udh) static const int EEPROM_PAGESIZE = 16; bool -usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, +usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, int eeprom_offset, const void *buf, int len) { unsigned char cmd[2]; @@ -1107,7 +1089,7 @@ usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, } bool -usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, +usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, int eeprom_offset, void *buf, int len) { unsigned char *p = (unsigned char *) buf; @@ -1169,7 +1151,7 @@ tx_slot_p (int slot) } bool -usrp_write_aux_dac (struct usb_dev_handle *udh, int slot, +usrp_write_aux_dac (struct libusb_device_handle *udh, int slot, int which_dac, int value) { int which_codec; @@ -1200,7 +1182,7 @@ usrp_write_aux_dac (struct usb_dev_handle *udh, int slot, bool -usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, +usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, int which_adc, int *value) { *value = 0; @@ -1279,7 +1261,7 @@ set_chksum (unsigned char *buf) } static usrp_dbeeprom_status_t -read_dboard_eeprom (struct usb_dev_handle *udh, +read_dboard_eeprom (struct libusb_device_handle *udh, int slot_id, unsigned char *buf) { int i2c_addr = slot_to_i2c_addr (slot_id); @@ -1303,7 +1285,7 @@ read_dboard_eeprom (struct usb_dev_handle *udh, } usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct usb_dev_handle *udh, +usrp_read_dboard_eeprom (struct libusb_device_handle *udh, int slot_id, usrp_dboard_eeprom *eeprom) { unsigned char buf[DB_EEPROM_CLEN]; @@ -1323,7 +1305,7 @@ usrp_read_dboard_eeprom (struct usb_dev_handle *udh, } bool -usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id, +usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, short offset0, short offset1) { unsigned char buf[DB_EEPROM_CLEN]; @@ -1343,15 +1325,19 @@ usrp_write_dboard_offsets (struct usb_dev_handle *udh, int slot_id, } std::string -usrp_serial_number(struct usb_dev_handle *udh) +usrp_serial_number(struct libusb_device_handle *udh) { - unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber; + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + unsigned char iserial = desc.iSerialNumber; if (iserial == 0) return ""; - char buf[1024]; - if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0) + unsigned char buf[1024]; + if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0) return ""; - return buf; + return (char*) buf; } diff --git a/usrp/host/swig/usrp_prims.i b/usrp/host/swig/usrp_prims.i index 78a775cf1..25a3968a8 100644 --- a/usrp/host/swig/usrp_prims.i +++ b/usrp/host/swig/usrp_prims.i @@ -42,8 +42,8 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; -struct usb_dev_handle; -struct usb_device; +struct libusb_device_handle; +struct libusb_device; /*! * \brief initialize libusb; probe busses and devices. @@ -63,20 +63,20 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct usb_device *usrp_find_device (int nth, bool fx2_ok_p = false); +struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false); -bool usrp_usrp_p (struct usb_device *q); //< is this a USRP -bool usrp_usrp0_p (struct usb_device *q); //< is this a USRP Rev 0 -bool usrp_usrp1_p (struct usb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (struct usb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (struct usb_device *q); //< return h/w rev code -bool usrp_fx2_p (struct usb_device *q); //< is this an unconfigured Cypress FX2 +bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP +bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 +bool usrp_usrp1_p (struct libusb_device *q); //< is this a USRP Rev 1 +bool usrp_usrp2_p (struct libusb_device *q); //< is this a USRP Rev 2 +int usrp_hw_rev (struct libusb_device *q); //< return h/w rev code +bool usrp_fx2_p (struct libusb_device *q); //< is this an unconfigured Cypress FX2 -bool usrp_unconfigured_usrp_p (struct usb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured USRP +bool usrp_unconfigured_usrp_p (struct libusb_device *q); //< some kind of unconfigured USRP +bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configured USRP /*! - * \brief given a usb_device return an instance of the appropriate usb_dev_handle + * \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!) @@ -84,14 +84,14 @@ bool usrp_configured_usrp_p (struct usb_device *q); //< some kind of configured * If interface can't be opened, or is already claimed by some other * process, 0 is returned. */ -struct usb_dev_handle *usrp_open_cmd_interface (struct usb_device *dev); -struct usb_dev_handle *usrp_open_rx_interface (struct usb_device *dev); -struct usb_dev_handle *usrp_open_tx_interface (struct usb_device *dev); +struct libusb_device_handle *usrp_open_cmd_interface (struct libusb_device *dev); +struct libusb_device_handle *usrp_open_rx_interface (struct libusb_device *dev); +struct libusb_device_handle *usrp_open_tx_interface (struct libusb_device *dev); /*! * \brief close interface. */ -bool usrp_close_interface (struct usb_dev_handle *udh); +bool usrp_close_interface (struct libusb_device_handle *udh); /*! * \brief load intel hex format file into USRP/Cypress FX2 (8051). @@ -103,7 +103,7 @@ bool usrp_close_interface (struct usb_dev_handle *udh); */ usrp_load_status_t -usrp_load_firmware (struct usb_dev_handle *udh, const char *filename, bool force); +usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load intel hex format file into USRP FX2 (8051). @@ -122,7 +122,7 @@ usrp_load_firmware_nth (int nth, const char *filename, bool force); * \brief load fpga configuration bitstream */ usrp_load_status_t -usrp_load_fpga (struct usb_dev_handle *udh, const char *filename, bool force); +usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load the regular firmware and fpga bitstream in the Nth USRP. @@ -136,12 +136,12 @@ bool usrp_load_standard_bits (int nth, bool force); %include -bool usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value); +bool usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value); %inline %{ int -usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg) +usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg) { int value; bool ok = usrp_read_fpga_reg (udh, reg, &value); @@ -153,37 +153,37 @@ usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg) %} -bool usrp_set_fpga_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (struct usb_dev_handle *udh, bool on); -bool usrp_set_led (struct usb_dev_handle *udh, int which, bool on); +bool usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on); +bool usrp_set_led (struct libusb_device_handle *udh, int which, bool on); -bool usrp_check_rx_overrun (struct usb_dev_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (struct usb_dev_handle *udh, bool *underrun_p); +bool usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p); +bool usrp_check_tx_underrun (struct 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 (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, void *buf, int len); -bool usrp_i2c_read (struct usb_dev_handle *udh, int i2c_addr, +bool usrp_i2c_read (struct 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 (struct usb_dev_handle *udh, +bool usrp_spi_write (struct libusb_device_handle *udh, int optional_header, int enables, int format, unsigned char *buf, int len); -bool usrp_spi_read (struct usb_dev_handle *udh, +bool usrp_spi_read (struct libusb_device_handle *udh, int optional_header, int enables, int format, unsigned char *buf, int len); -bool usrp_9862_write (struct usb_dev_handle *udh, +bool usrp_9862_write (struct libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] int value); // [0, 255] @@ -191,7 +191,7 @@ bool usrp_9862_write (struct usb_dev_handle *udh, %inline %{ int -usrp_9862_read (struct usb_dev_handle *udh, int which_codec, int reg) +usrp_9862_read (struct libusb_device_handle *udh, int which_codec, int reg) { unsigned char value; bool ok = usrp_9862_read (udh, which_codec, reg, &value); @@ -206,7 +206,7 @@ usrp_9862_read (struct usb_dev_handle *udh, int which_codec, int reg) %inline %{ bool -usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, +usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, int eeprom_offset, const std::string buf) { return usrp_eeprom_write (udh, i2c_addr, eeprom_offset, @@ -214,7 +214,7 @@ usrp_eeprom_write (struct usb_dev_handle *udh, int i2c_addr, } std::string -usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, +usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, int eeprom_offset, int len) { if (len <= 0) @@ -230,12 +230,12 @@ usrp_eeprom_read (struct usb_dev_handle *udh, int i2c_addr, %} -bool usrp_write_aux_dac (struct usb_dev_handle *uhd, int slot, +bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, int which_dac, int value); %inline %{ -int usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, int which_adc) +int usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, int which_adc) { int value; bool ok = usrp_read_aux_adc (udh, slot, which_adc, &value); @@ -253,7 +253,7 @@ int usrp_read_aux_adc (struct usb_dev_handle *udh, int slot, int which_adc) * Note that this only works on a configured usrp. * \returns non-zero length string iff successful. */ -std::string usrp_serial_number(struct usb_dev_handle *udh); +std::string usrp_serial_number(struct libusb_device_handle *udh); /*! * \brief usrp daughterboard id to name mapping -- cgit From 0854c4604fcbdb64c74e4b93b87ac07be3d75f55 Mon Sep 17 00:00:00 2001 From: ttsou Date: Tue, 25 Aug 2009 14:53:34 -0400 Subject: Fix for simultaneous tx-rx using libusb_contexts --- usrp/host/include/usrp/usrp_basic.h | 1 + usrp/host/include/usrp/usrp_prims.h | 15 +++++--- usrp/host/lib/fusb.h | 4 +- usrp/host/lib/fusb_libusb1.cc | 67 +++++++++++++++++---------------- usrp/host/lib/fusb_libusb1.h | 8 +++- usrp/host/lib/fusb_sysconfig_libusb1.cc | 6 ++- usrp/host/lib/usrp_basic.cc | 24 ++++++------ usrp/host/lib/usrp_prims.cc | 60 ++++++++++++++++++++--------- 8 files changed, 112 insertions(+), 73 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h index c79908a86..2430ff5c4 100644 --- a/usrp/host/include/usrp/usrp_basic.h +++ b/usrp/host/include/usrp/usrp_basic.h @@ -66,6 +66,7 @@ protected: protected: struct 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; diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h index df410b408..05ad0046e 100644 --- a/usrp/host/include/usrp/usrp_prims.h +++ b/usrp/host/include/usrp/usrp_prims.h @@ -43,12 +43,16 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; struct libusb_device_handle; struct libusb_device; +struct libusb_context; /*! * \brief initialize libusb; probe busses and devices. - * Safe to call more than once. + * 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. */ -void usrp_one_time_init (); +libusb_context* usrp_one_time_init (bool new_context); /* * force a rescan of the buses and devices @@ -65,7 +69,7 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false); +struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL); bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 @@ -119,7 +123,7 @@ usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool * then rescans the busses and devices. */ usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force); +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx); /*! * \brief load fpga configuration bitstream @@ -134,7 +138,8 @@ usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool for */ bool usrp_load_standard_bits (int nth, bool force, const std::string fpga_filename = "", - const std::string firmware_filename = ""); + const std::string firmware_filename = "", + libusb_context *ctx = NULL); /*! * \brief copy the given \p hash into the USRP hash slot \p which. diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index bfe34d5b8..fbd651204 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -27,6 +27,7 @@ struct libusb_device_handle; +struct libusb_context; class fusb_ephandle; /*! @@ -116,7 +117,8 @@ public: /*! * \brief returns fusb_devhandle or throws if trouble */ - static fusb_devhandle *make_devhandle (libusb_device_handle *udh); + static fusb_devhandle *make_devhandle (libusb_device_handle *udh, + libusb_context *ctx); /*! * \brief Returns max block size in bytes (hard limit). diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 07e05c230..0559022bb 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -124,8 +124,9 @@ alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, // device handle // ------------------------------------------------------------------------ -fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh) - : fusb_devhandle (udh), d_teardown (false) +fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh, + libusb_context *ctx) + : fusb_devhandle (udh), d_ctx (ctx), d_teardown (false) { // that's it } @@ -258,6 +259,24 @@ fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) } +/* + * Reimplementing _reap for context use and compatibiliy with libusb-0.12. + * Returns false on error, true otherwise. + */ + +bool +fusb_devhandle_libusb1::_reap (bool ok_to_block_p) +{ + int ret; + + if ((ret = libusb_handle_events(d_ctx)) < 0) { + fprintf (stderr, "fusb::_reap libusb_handle_events()\n"); + return false; + } + + return true; +} + void fusb_devhandle_libusb1::_wait_for_completion () { @@ -267,17 +286,9 @@ fusb_devhandle_libusb1::_wait_for_completion () tv.tv_sec = 1; tv.tv_usec = 0; - // The regular libusb_handle_events sets a hardcoded timeout of 2 - // seconds. Most of these calls should be changed to appropriate block / non- - // blocking version using libusb_handle_events_timeout. This was just a test - // usage. - - while (!d_pending_rqsts.empty ()) { - if ((ret = libusb_handle_events_timeout(NULL, &tv)) < 0) { - fprintf (stderr, "fusb: libusb_handle_events error %d\n", ret); - break; - } - } + while (!d_pending_rqsts.empty ()) + if (!_reap(true)) + break; } @@ -346,7 +357,6 @@ fusb_ephandle_libusb1::~fusb_ephandle_libusb1 () bool fusb_ephandle_libusb1::start () { - if (d_started) return true; @@ -390,12 +400,7 @@ fusb_ephandle_libusb1::stop () } d_devhandle->_cancel_pending_rqsts (this); - - // Do work, reap transfers, etc. - if (libusb_handle_events(NULL) < 0) { - perror ("fusb::libusb_handle_events"); - return false; - } + d_devhandle->_reap (false); while (1) { libusb_transfer *lut; @@ -405,15 +410,13 @@ fusb_ephandle_libusb1::stop () if (d_free_list.size () == (unsigned) d_nblocks) break; - if (libusb_handle_events(NULL) < 0) { - perror ("fusb::libusb_handle_events"); - return false; - } + if (!d_devhandle->_reap(true)) + break; } d_started = false; - return true; + return true; } // ------------------------------------------------------------------------ @@ -425,7 +428,6 @@ fusb_ephandle_libusb1::stop () int fusb_ephandle_libusb1::write (const void *buffer, int nbytes) { - if (!d_started) // doesn't matter here, but keeps semantics constant return -1; @@ -456,7 +458,7 @@ fusb_ephandle_libusb1::write (const void *buffer, int nbytes) d_write_work_in_progress = 0; } - return nbytes; + return n; } #else @@ -515,8 +517,8 @@ fusb_ephandle_libusb1::get_write_work_in_progress () return lut; } - // Do work, reap transfers, etc. - libusb_handle_events(NULL); + if (!d_devhandle->_reap (true)) + return 0; } } @@ -603,10 +605,9 @@ fusb_ephandle_libusb1::reload_read_buffer () while (1) { - while ((lut = completed_list_get ()) == 0 ) { - if (libusb_handle_events(NULL) < 0) - fprintf (stderr, "fusb: libusb_handle_events\n"); - } + while ((lut = completed_list_get ()) == 0 ) + if (!d_devhandle->_reap(true)) + return false; if (lut->status != LIBUSB_TRANSFER_COMPLETED) { fprintf (stderr, "fust: (rd status %d) %s\n", lut->status, diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h index 1661b7ab8..4bc49aafb 100644 --- a/usrp/host/lib/fusb_libusb1.h +++ b/usrp/host/lib/fusb_libusb1.h @@ -27,6 +27,8 @@ #include struct libusb_transfer; +struct libusb_context; + class fusb_ephandle_libusb1; /*! @@ -35,7 +37,8 @@ class fusb_ephandle_libusb1; class fusb_devhandle_libusb1 : public fusb_devhandle { private: - std::list d_pending_rqsts; + std::list d_pending_rqsts; + libusb_context *d_ctx; void pending_add (struct libusb_transfer *lut); struct libusb_transfer * pending_get (); @@ -44,7 +47,7 @@ private: public: // CREATORS - fusb_devhandle_libusb1 (libusb_device_handle *udh); + fusb_devhandle_libusb1 (libusb_device_handle *udh, libusb_context *ctx); virtual ~fusb_devhandle_libusb1 (); // MANIPULATORS @@ -54,6 +57,7 @@ public: bool _submit_lut (libusb_transfer *); bool _cancel_lut (libusb_transfer *); void _cancel_pending_rqsts (fusb_ephandle_libusb1 *eph); + bool _reap (bool ok_to_block_p); void _wait_for_completion (); // accessors to work from callback context diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index e0d9458e1..c82bfe9a1 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -27,10 +27,12 @@ static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit static const int DEFAULT_BLOCK_SIZE = 4 * 1024; static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB +struct libusb_context; + fusb_devhandle * -fusb_sysconfig::make_devhandle (libusb_device_handle *udh) +fusb_sysconfig::make_devhandle (libusb_device_handle *udh, libusb_context *ctx) { - return new fusb_devhandle_libusb1 (udh); + return new fusb_devhandle_libusb1 (udh, ctx); } int fusb_sysconfig::max_block_size () diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc index a8b44edab..3a0368894 100644 --- a/usrp/host/lib/usrp_basic.cc +++ b/usrp/host/lib/usrp_basic.cc @@ -108,7 +108,7 @@ usrp_basic::usrp_basic (int which_board, open_interface (struct libusb_device *dev), const std::string fpga_filename, const std::string firmware_filename) - : d_udh (0), + : d_udh (0), d_ctx (0), d_usb_data_rate (16000000), // SWAG, see below d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) @@ -125,12 +125,12 @@ usrp_basic::usrp_basic (int which_board, */ memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); - usrp_one_time_init (); + d_ctx = usrp_one_time_init(true); - if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx)) throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); - struct libusb_device *dev = usrp_find_device (which_board); + struct libusb_device *dev = usrp_find_device (which_board, false, d_ctx); if (dev == 0){ fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); throw std::runtime_error ("usrp_basic/usrp_find_device"); @@ -153,6 +153,7 @@ usrp_basic::usrp_basic (int which_board, _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs + } void @@ -175,12 +176,11 @@ usrp_basic::~usrp_basic () if (d_udh) libusb_close (d_udh); - // There's no reference count on the number of times libusb is initialized. - // libusb_init can be called multiple times, but libusb_exit shuts down - // everything. Leave libusb running for now. Need to add a count so that it - // exits nicely. + // Each object should be running in it's own context. If running in default + // (NULL) context then something went wrong. - //libusb_exit (NULL); + assert (d_ctx != NULL); + libusb_exit (d_ctx); } void @@ -819,7 +819,7 @@ usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nbl if (fusb_nblocks == 0) fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); - d_devhandle = fusb_sysconfig::make_devhandle (d_udh); + d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true, fusb_block_size, fusb_nblocks); @@ -870,7 +870,7 @@ usrp_basic_rx::start () fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); return false; } - + return true; } @@ -1222,7 +1222,7 @@ usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nbl if (fusb_nblocks == 0) fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); - d_devhandle = fusb_sysconfig::make_devhandle (d_udh); + d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false, fusb_block_size, fusb_nblocks); diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc index e1e3e3074..d651a4529 100644 --- a/usrp/host/lib/usrp_prims.cc +++ b/usrp/host/lib/usrp_prims.cc @@ -103,15 +103,30 @@ get_proto_filename(const std::string user_filename, const char *env_var, const c static void power_down_9862s (struct libusb_device_handle *udh); -void -usrp_one_time_init () +libusb_context * +usrp_one_time_init (bool new_context) { + static bool first = true; + libusb_context *ctx = NULL; + int ret; - if (first){ + // On first call create default context in addition to any new requested + // context. The default context is probably useless in this form, but keep + // it for now due to compatibility reasons. + + if (first) { first = false; - libusb_init (NULL); // usb library init + if ((ret = libusb_init (NULL)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); } + + if (new_context) { + if ((ret = libusb_init (&ctx)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); + } + + return ctx; } void @@ -204,16 +219,17 @@ usrp_configured_usrp_p (struct libusb_device *q) // ---------------------------------------------------------------- struct libusb_device * -usrp_find_device (int nth, bool fx2_ok_p) +usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) { libusb_device **list; struct libusb_device *q; int n_found = 0; - usrp_one_time_init (); - - size_t cnt = libusb_get_device_list(NULL, &list); +//usrp_one_time_init (false); + assert (ctx != NULL); + + size_t cnt = libusb_get_device_list(ctx, &list); size_t i = 0; if (cnt < 0) @@ -228,7 +244,12 @@ usrp_find_device (int nth, bool fx2_ok_p) } } +/* + * The list needs to be freed. Right just release it if nothing is found. + */ + libusb_free_device_list(list, 1); + return 0; // not found } @@ -727,9 +748,10 @@ usrp_load_fpga (struct libusb_device_handle *udh, } static libusb_device_handle * -open_nth_cmd_interface (int nth) +open_nth_cmd_interface (int nth, libusb_context *ctx) { - struct libusb_device *udev = usrp_find_device (nth); + + struct libusb_device *udev = usrp_find_device (nth, false, ctx); if (udev == 0){ fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); return 0; @@ -777,8 +799,9 @@ mdelay (int millisecs) } usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force){ - struct libusb_device_handle *udh = open_nth_cmd_interface (nth); +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx) +{ + struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); if (udh == 0) return ULS_ERROR; @@ -839,16 +862,19 @@ load_status_msg (usrp_load_status_t s, const char *type, const char *filename) bool usrp_load_standard_bits (int nth, bool force, const std::string fpga_filename, - const std::string firmware_filename) + const std::string firmware_filename, + libusb_context *ctx) { usrp_load_status_t s; const char *filename; const char *proto_filename; int hw_rev; + assert (ctx != NULL); + // first, figure out what hardware rev we're dealing with { - struct libusb_device *udev = usrp_find_device (nth); + struct libusb_device *udev = usrp_find_device (nth, false, ctx); if (udev == 0){ fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); return false; @@ -865,8 +891,7 @@ usrp_load_standard_bits (int nth, bool force, fprintf (stderr, "Can't find firmware: %s\n", proto_filename); return false; } - - s = usrp_load_firmware_nth (nth, filename, force); + s = usrp_load_firmware_nth (nth, filename, force, ctx); load_status_msg (s, "firmware", filename); if (s == ULS_ERROR) @@ -885,8 +910,7 @@ usrp_load_standard_bits (int nth, bool force, fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); return false; } - - struct libusb_device_handle *udh = open_nth_cmd_interface (nth); + struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); if (udh == 0) return false; -- cgit From 3d3888c40ac46cbbd8851e9bc5e83557e0415887 Mon Sep 17 00:00:00 2001 From: ttsou Date: Tue, 25 Aug 2009 18:46:14 -0400 Subject: non-blocking reap and fusb default buffer size change --- usrp/host/lib/fusb_libusb1.cc | 17 +++++++++++------ usrp/host/lib/fusb_sysconfig_libusb1.cc | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 0559022bb..6f1fc913f 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -268,8 +268,18 @@ bool fusb_devhandle_libusb1::_reap (bool ok_to_block_p) { int ret; + struct timeval tv; - if ((ret = libusb_handle_events(d_ctx)) < 0) { + if (ok_to_block_p) { + tv.tv_sec = 2; + tv.tv_usec = 0; + } + else { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + if ((ret = libusb_handle_events_timeout(d_ctx, &tv)) < 0) { fprintf (stderr, "fusb::_reap libusb_handle_events()\n"); return false; } @@ -281,11 +291,6 @@ void fusb_devhandle_libusb1::_wait_for_completion () { - int ret; - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - while (!d_pending_rqsts.empty ()) if (!_reap(true)) break; diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index c82bfe9a1..a005f540d 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -25,7 +25,7 @@ static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit static const int DEFAULT_BLOCK_SIZE = 4 * 1024; -static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB +static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1 MB struct libusb_context; -- cgit From 0d7fa4aac5b01cf463e1a065205094cd494853ee Mon Sep 17 00:00:00 2001 From: ttsou Date: Tue, 25 Aug 2009 19:30:39 -0400 Subject: Additional comments for reaping transactions --- usrp/host/lib/fusb_libusb1.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 6f1fc913f..dc51d5709 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -261,7 +261,13 @@ fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) /* * Reimplementing _reap for context use and compatibiliy with libusb-0.12. - * Returns false on error, true otherwise. + * + * Returns false on timeout or error, true if an event was handled + * + * If ok_to_block_p is false then handle already pending events and return + * immediately. + * If ok_to_block_p is true then call libusb_handle_events_timeout with default + * timeout value of 2 seconds, which returns on event arrival or timeout. */ bool @@ -279,8 +285,9 @@ fusb_devhandle_libusb1::_reap (bool ok_to_block_p) tv.tv_usec = 0; } + if ((ret = libusb_handle_events_timeout(d_ctx, &tv)) < 0) { - fprintf (stderr, "fusb::_reap libusb_handle_events()\n"); + fprintf (stderr, "fusb::_reap libusb_handle_events() %i\n", ret); return false; } -- cgit From 117bee2b2b88b5d348db1a8f6beb28de8340f407 Mon Sep 17 00:00:00 2001 From: ttsou Date: Tue, 25 Aug 2009 19:52:29 -0400 Subject: Additional comments for reaping transactions --- usrp/host/lib/fusb_libusb1.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index dc51d5709..e50e44081 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -266,8 +266,10 @@ fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) * * If ok_to_block_p is false then handle already pending events and return * immediately. + * * If ok_to_block_p is true then call libusb_handle_events_timeout with default - * timeout value of 2 seconds, which returns on event arrival or timeout. + * timeout value of 2 seconds, which waits and returns on event arrival or + * timeout. */ bool @@ -285,7 +287,6 @@ fusb_devhandle_libusb1::_reap (bool ok_to_block_p) tv.tv_usec = 0; } - if ((ret = libusb_handle_events_timeout(d_ctx, &tv)) < 0) { fprintf (stderr, "fusb::_reap libusb_handle_events() %i\n", ret); return false; -- cgit From bdec6a37a474b961389e0ac590d0582e490ffb2c Mon Sep 17 00:00:00 2001 From: ttsou Date: Wed, 26 Aug 2009 10:46:56 -0400 Subject: Modify apps and swig to reflect libusb_context use --- usrp/host/apps/usrper.cc | 4 ++-- usrp/host/swig/usrp_prims.i | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc index 1c4beb713..9c6403c9d 100644 --- a/usrp/host/apps/usrper.cc +++ b/usrp/host/apps/usrper.cc @@ -191,10 +191,10 @@ main (int argc, char **argv) const char *cmd = argv[optind++]; nopts--; - usrp_one_time_init (); + libusb_context *ctx = usrp_one_time_init (true); - struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p); + struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p, ctx); if (udev == 0){ fprintf (stderr, "%s: failed to find usrp[%d]\n", prog_name, which_board); exit (1); diff --git a/usrp/host/swig/usrp_prims.i b/usrp/host/swig/usrp_prims.i index 25a3968a8..a93d14cac 100644 --- a/usrp/host/swig/usrp_prims.i +++ b/usrp/host/swig/usrp_prims.i @@ -49,7 +49,7 @@ struct libusb_device; * \brief initialize libusb; probe busses and devices. * Safe to call more than once. */ -void usrp_one_time_init (); +struct libusb_context *usrp_one_time_init (bool new_context); void usrp_rescan (); @@ -63,7 +63,7 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false); +struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, struct libusb_context *ctx); bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 @@ -116,7 +116,7 @@ usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool * then rescans the busses and devices. */ usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force); +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx); /*! * \brief load fpga configuration bitstream -- cgit From c62085a66bd97f389f49167492f7dccfb0b02976 Mon Sep 17 00:00:00 2001 From: ttsou Date: Thu, 27 Aug 2009 18:13:54 -0400 Subject: first shot at re-adding libusb-0.12 support --- usrp/host/include/usrp/usrp_basic.h | 12 +- usrp/host/include/usrp/usrp_prims.h | 96 +- usrp/host/lib/Makefile.am | 14 +- usrp/host/lib/fusb.h | 8 + usrp/host/lib/fusb_sysconfig_linux.cc | 6 + usrp/host/lib/usrp_basic.cc | 1546 --------------------------------- usrp/host/lib/usrp_basic_common.cc | 1481 +++++++++++++++++++++++++++++++ usrp/host/lib/usrp_basic_libusb.cc | 146 ++++ usrp/host/lib/usrp_prims.cc | 1367 ----------------------------- usrp/host/lib/usrp_prims_common.cc | 965 ++++++++++++++++++++ usrp/host/lib/usrp_prims_libusb.cc | 490 +++++++++++ 11 files changed, 3168 insertions(+), 2963 deletions(-) delete mode 100644 usrp/host/lib/usrp_basic.cc create mode 100644 usrp/host/lib/usrp_basic_common.cc create mode 100644 usrp/host/lib/usrp_basic_libusb.cc delete mode 100644 usrp/host/lib/usrp_prims.cc create mode 100644 usrp/host/lib/usrp_prims_common.cc create mode 100644 usrp/host/lib/usrp_prims_libusb.cc (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h index 2430ff5c4..3ec734113 100644 --- a/usrp/host/include/usrp/usrp_basic.h +++ b/usrp/host/include/usrp/usrp_basic.h @@ -46,7 +46,15 @@ #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; @@ -65,7 +73,7 @@ protected: void shutdown_daughterboards(); protected: - struct libusb_device_handle *d_udh; + 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 @@ -92,7 +100,7 @@ protected: usrp_basic (int which_board, - struct libusb_device_handle *open_interface (struct libusb_device *dev), + libusb_device_handle *open_interface (libusb_device *dev), const std::string fpga_filename = "", const std::string firmware_filename = ""); diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h index 05ad0046e..bd7779b64 100644 --- a/usrp/host/include/usrp/usrp_prims.h +++ b/usrp/host/include/usrp/usrp_prims.h @@ -41,8 +41,16 @@ 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; /*! @@ -54,6 +62,8 @@ struct libusb_context; */ libusb_context* usrp_one_time_init (bool new_context); +void usrp_one_time_init (); + /* * force a rescan of the buses and devices */ @@ -69,18 +79,18 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL); +libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx = NULL); -bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP -bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 -bool usrp_usrp1_p (struct libusb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (struct libusb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (struct libusb_device *q); //< return h/w rev code +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 (struct libusb_device *q); //< is this an unconfigured Cypress FX2 +bool usrp_fx2_p (libusb_device *q); //< is this an unconfigured Cypress FX2 -bool usrp_unconfigured_usrp_p (struct libusb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configured USRP +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 @@ -91,14 +101,14 @@ bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configur * If interface can't be opened, or is already claimed by some other * process, 0 is returned. */ -struct libusb_device_handle *usrp_open_cmd_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_rx_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_tx_interface (struct libusb_device *dev); +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 (struct libusb_device_handle *udh); +bool usrp_close_interface (libusb_device_handle *udh); /*! * \brief load intel hex format file into USRP/Cypress FX2 (8051). @@ -110,7 +120,7 @@ bool usrp_close_interface (struct libusb_device_handle *udh); */ usrp_load_status_t -usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_firmware (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load intel hex format file into USRP FX2 (8051). @@ -123,13 +133,13 @@ usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool * then rescans the busses and devices. */ usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx); +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 (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_fpga (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load the regular firmware and fpga bitstream in the Nth USRP. @@ -145,54 +155,54 @@ bool usrp_load_standard_bits (int nth, bool force, * \brief copy the given \p hash into the USRP hash slot \p which. * The usrp implements two hash slots, 0 and 1. */ -bool usrp_set_hash (struct libusb_device_handle *udh, int which, +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 (struct libusb_device_handle *udh, int which, +bool usrp_get_hash (libusb_device_handle *udh, int which, unsigned char hash[USRP_HASH_SIZE]); -bool usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value); -bool usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value); -bool usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_led (struct libusb_device_handle *udh, int which, bool on); +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 (struct libusb_device_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p); +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 (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, const void *buf, int len); -bool usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, +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 (struct libusb_device_handle *udh, +bool usrp_spi_write (libusb_device_handle *udh, int optional_header, int enables, int format, const void *buf, int len); -bool usrp_spi_read (struct libusb_device_handle *udh, +bool usrp_spi_read (libusb_device_handle *udh, int optional_header, int enables, int format, void *buf, int len); -bool usrp_9862_write (struct libusb_device_handle *udh, +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 (struct libusb_device_handle *udh, +bool usrp_9862_read (libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] unsigned char *value); // [0, 255] @@ -203,28 +213,28 @@ bool usrp_9862_read (struct libusb_device_handle *udh, * \p buf contains alternating register_number, register_value pairs. * \p len must be even and is the length of buf in bytes. */ -bool usrp_9862_write_many (struct libusb_device_handle *udh, int which_codec, +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 (struct libusb_device_handle *udh, +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 (struct libusb_device_handle *udh, int i2c_addr, +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 (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, void *buf, int len); @@ -246,7 +256,7 @@ bool usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, * binary values. Although dacs 0, 1 and 2 are 8-bit and dac 3 is 12-bit, * the interface is in terms of 12-bit values [0,4095] */ -bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, +bool usrp_write_aux_dac (libusb_device_handle *uhd, int slot, int which_dac, int value); /*! @@ -256,7 +266,7 @@ bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, * \p which_adc: [0,1] which of the two adcs to read * \p *value: return value, 12-bit straight binary. */ -bool usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, +bool usrp_read_aux_adc (libusb_device_handle *udh, int slot, int which_adc, int *value); @@ -279,13 +289,13 @@ struct usrp_dboard_eeprom { * \brief Read and return parsed daughterboard eeprom */ usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct libusb_device_handle *udh, +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 (struct libusb_device_handle *udh, int slot_id, +bool usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, short offset0, short offset1); /*! @@ -294,6 +304,6 @@ bool usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, * Note that this only works on a configured usrp. * \returns non-zero length string iff successful. */ -std::string usrp_serial_number(struct libusb_device_handle *udh); +std::string usrp_serial_number(libusb_device_handle *udh); #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index e7c3f34c4..4dd47595e 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -78,7 +78,9 @@ win32_CODE = \ linux_CODE = \ fusb_linux.cc \ - fusb_sysconfig_linux.cc + fusb_sysconfig_linux.cc \ + usrp_prims_libusb.cc \ + usrp_basic_libusb.cc ra_wb_CODE = \ fusb_ra_wb.cc \ @@ -86,7 +88,9 @@ ra_wb_CODE = \ libusb1_CODE = \ fusb_libusb1.cc \ - fusb_sysconfig_libusb1.cc + fusb_sysconfig_libusb1.cc \ + usrp_prims_libusb1.cc \ + usrp_basic_libusb1.cc # # include each _CODE entry here... @@ -103,17 +107,17 @@ EXTRA_libusrp_la_SOURCES = \ libusrp_la_common_SOURCES = \ fusb.cc \ md5.c \ - usrp_basic.cc \ + usrp_basic_common.cc \ usrp_config.cc \ usrp_dbid.cc \ usrp_local_sighandler.cc \ - usrp_prims.cc \ + usrp_prims_common.cc \ usrp_standard.cc \ db_boards.cc \ db_base.cc \ db_basic.cc \ db_tv_rx.cc \ - db_tv_rx_mimo.cc \ + db_tv_rx_mimo.cc \ db_flexrf.cc \ db_flexrf_mimo.cc \ db_dbs_rx.cc \ diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index fbd651204..24d2bee6e 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -26,7 +26,13 @@ #define _FUSB_H_ +#if 1 +struct usb_dev_handle; +typedef struct usb_dev_handle libusb_device_handle; +#else struct libusb_device_handle; +#endif + struct libusb_context; class fusb_ephandle; @@ -120,6 +126,8 @@ public: static fusb_devhandle *make_devhandle (libusb_device_handle *udh, libusb_context *ctx); + static fusb_devhandle *make_devhandle (libusb_device_handle *udh); + /*! * \brief Returns max block size in bytes (hard limit). */ diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index 3c2f59375..8f56f61e2 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -33,6 +33,12 @@ fusb_sysconfig::make_devhandle (usb_dev_handle *udh) return new fusb_devhandle_linux (udh); } +fusb_devhandle * +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) +{ + return new fusb_devhandle_linux (udh); +} + int fusb_sysconfig::max_block_size () { return MAX_BLOCK_SIZE; diff --git a/usrp/host/lib/usrp_basic.cc b/usrp/host/lib/usrp_basic.cc deleted file mode 100644 index 3a0368894..000000000 --- a/usrp/host/lib/usrp_basic.cc +++ /dev/null @@ -1,1546 +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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "usrp/usrp_prims.h" -#include "usrp_interfaces.h" -#include "fpga_regs_common.h" -#include "fpga_regs_standard.h" -#include "fusb.h" -#include "db_boards.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace ad9862; - -#define NELEM(x) (sizeof (x) / sizeof (x[0])) - -// These set the buffer size used for each end point using the fast -// usb interface. The kernel ends up locking down this much memory. - -static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); -static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); -static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; - - -static const double POLLING_INTERVAL = 0.1; // seconds - -//////////////////////////////////////////////////////////////// - -static struct libusb_device_handle * -open_rx_interface (struct libusb_device *dev) -{ - struct libusb_device_handle *udh = usrp_open_rx_interface (dev); - if (udh == 0){ - fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); - } - return udh; -} - -static struct libusb_device_handle * -open_tx_interface (struct libusb_device *dev) -{ - struct libusb_device_handle *udh = usrp_open_tx_interface (dev); - if (udh == 0){ - fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); - } - return udh; -} - - -////////////////////////////////////////////////////////////////// -// -// usrp_basic -// -//////////////////////////////////////////////////////////////// - - -// Given: -// CLKIN = 64 MHz -// CLKSEL pin = high -// -// These settings give us: -// CLKOUT1 = CLKIN = 64 MHz -// CLKOUT2 = CLKIN = 64 MHz -// ADC is clocked at 64 MHz -// DAC is clocked at 128 MHz - -static unsigned char common_regs[] = { - REG_GENERAL, 0, - REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC - | DLL_MULT_2X - | DLL_FAST), - REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, - REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 -}; - - -usrp_basic::usrp_basic (int which_board, - struct libusb_device_handle * - open_interface (struct libusb_device *dev), - const std::string fpga_filename, - const std::string firmware_filename) - : d_udh (0), d_ctx (0), - d_usb_data_rate (16000000), // SWAG, see below - d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), - d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) -{ - /* - * SWAG: Scientific Wild Ass Guess. - * - * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. - * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., - * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the - * actual rate. This doesn't change our throughput, that's determined by the signal - * processing code in the FPGA (which we know nothing about), and the system limits - * determined by libusb, fusb_*, and the underlying drivers. - */ - memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); - - d_ctx = usrp_one_time_init(true); - - if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx)) - throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); - - struct libusb_device *dev = usrp_find_device (which_board, false, d_ctx); - if (dev == 0){ - fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); - throw std::runtime_error ("usrp_basic/usrp_find_device"); - } - - if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ - fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); - throw std::runtime_error ("usrp_basic/bad_rev"); - } - - if ((d_udh = open_interface (dev)) == 0) - throw std::runtime_error ("usrp_basic/open_interface"); - - // initialize registers that are common to rx and tx - - if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ - fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); - throw std::runtime_error ("usrp_basic/init_9862"); - } - - _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode - _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs - -} - -void -usrp_basic::shutdown_daughterboards() -{ - // nuke d'boards before we close down USB in ~usrp_basic - // shutdown() will do any board shutdown while the USRP can still - // be talked to - for(size_t i = 0; i < d_db.size(); i++) - for(size_t j = 0; j < d_db[i].size(); j++) - d_db[i][j]->shutdown(); -} - -usrp_basic::~usrp_basic () -{ - // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} - - d_db.resize(0); // forget db shared ptrs - - if (d_udh) - libusb_close (d_udh); - - // Each object should be running in it's own context. If running in default - // (NULL) context then something went wrong. - - assert (d_ctx != NULL); - libusb_exit (d_ctx); -} - -void -usrp_basic::init_db(usrp_basic_sptr u) -{ - if (u.get() != this) - throw std::invalid_argument("u is not this"); - - d_db[0] = instantiate_dbs(d_dbid[0], u, 0); - d_db[1] = instantiate_dbs(d_dbid[1], u, 1); -} - -std::vector -usrp_basic::db(int which_side) -{ - which_side &= 0x1; // clamp it to avoid any reporting any errors - return d_db[which_side]; -} - -bool -usrp_basic::is_valid(const usrp_subdev_spec &ss) -{ - if (ss.side < 0 || ss.side > 1) - return false; - - if (ss.subdev < 0 || ss.subdev >= d_db[ss.side].size()) - return false; - - return true; -} - -db_base_sptr -usrp_basic::selected_subdev(const usrp_subdev_spec &ss) -{ - if (!is_valid(ss)) - throw std::invalid_argument("invalid subdev_spec"); - - return d_db[ss.side][ss.subdev]; -} - -bool -usrp_basic::start () -{ - return true; // nop -} - -bool -usrp_basic::stop () -{ - return true; // nop -} - -void -usrp_basic::set_usb_data_rate (int usb_data_rate) -{ - d_usb_data_rate = usb_data_rate; - d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL); -} - -bool -usrp_basic::_write_aux_dac (int slot, int which_dac, int value) -{ - return usrp_write_aux_dac (d_udh, slot, which_dac, value); -} - -bool -usrp_basic::_read_aux_adc (int slot, int which_adc, int *value) -{ - return usrp_read_aux_adc (d_udh, slot, which_adc, value); -} - -int -usrp_basic::_read_aux_adc (int slot, int which_adc) -{ - int value; - if (!_read_aux_adc (slot, which_adc, &value)) - return READ_FAILED; - - return value; -} - -bool -usrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) -{ - return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ()); -} - -std::string -usrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len) -{ - if (len <= 0) - return ""; - - char buf[len]; - - if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len)) - return ""; - - return std::string (buf, len); -} - -bool -usrp_basic::write_i2c (int i2c_addr, const std::string buf) -{ - return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ()); -} - -std::string -usrp_basic::read_i2c (int i2c_addr, int len) -{ - if (len <= 0) - return ""; - - char buf[len]; - - if (!usrp_i2c_read (d_udh, i2c_addr, buf, len)) - return ""; - - return std::string (buf, len); -} - -std::string -usrp_basic::serial_number() -{ - return usrp_serial_number(d_udh); -} - -// ---------------------------------------------------------------- - -bool -usrp_basic::set_adc_offset (int which_adc, int offset) -{ - if (which_adc < 0 || which_adc > 3) - return false; - - return _write_fpga_reg (FR_ADC_OFFSET_0 + which_adc, offset); -} - -bool -usrp_basic::set_dac_offset (int which_dac, int offset, int offset_pin) -{ - if (which_dac < 0 || which_dac > 3) - return false; - - int which_codec = which_dac >> 1; - int tx_a = (which_dac & 0x1) == 0; - int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1); - int hi = (offset >> 2); - bool ok; - - if (tx_a){ - ok = _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo); - ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi); - } - else { - ok = _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo); - ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi); - } - return ok; -} - -bool -usrp_basic::set_adc_buffer_bypass (int which_adc, bool bypass) -{ - if (which_adc < 0 || which_adc > 3) - return false; - - int codec = which_adc >> 1; - int reg = (which_adc & 1) == 0 ? REG_RX_A : REG_RX_B; - - unsigned char cur_rx; - unsigned char cur_pwr_dn; - - // If the input buffer is bypassed, we need to power it down too. - - bool ok = _read_9862 (codec, reg, &cur_rx); - ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn); - if (!ok) - return false; - - if (bypass){ - cur_rx |= RX_X_BYPASS_INPUT_BUFFER; - cur_pwr_dn |= ((which_adc & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B; - } - else { - cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER; - cur_pwr_dn &= ~(((which_adc & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B); - } - - ok &= _write_9862 (codec, reg, cur_rx); - ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn); - return ok; -} - -bool -usrp_basic::set_dc_offset_cl_enable(int bits, int mask) -{ - return _write_fpga_reg(FR_DC_OFFSET_CL_EN, - (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask)); -} - -// ---------------------------------------------------------------- - -bool -usrp_basic::_write_fpga_reg (int regno, int value) -{ - if (d_verbose){ - fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value); - fflush (stdout); - } - - if (regno >= 0 && regno < MAX_REGS) - d_fpga_shadows[regno] = value; - - return usrp_write_fpga_reg (d_udh, regno, value); -} - -bool -usrp_basic::_write_fpga_reg_masked (int regno, int value, int mask) -{ - //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE - //value is a 16 bits value and mask is a 16 bits mask - if (d_verbose){ - fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask); - fflush (stdout); - } - - if (regno >= 0 && regno < MAX_REGS) - d_fpga_shadows[regno] = value; - - return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16)); -} - - -bool -usrp_basic::_read_fpga_reg (int regno, int *value) -{ - return usrp_read_fpga_reg (d_udh, regno, value); -} - -int -usrp_basic::_read_fpga_reg (int regno) -{ - int value; - if (!_read_fpga_reg (regno, &value)) - return READ_FAILED; - return value; -} - -bool -usrp_basic::_write_9862 (int which_codec, int regno, unsigned char value) -{ - if (0 && d_verbose){ - // FIXME really want to enable logging in usrp_prims:usrp_9862_write - fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value); - fflush(stdout); - } - - return usrp_9862_write (d_udh, which_codec, regno, value); -} - - -bool -usrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const -{ - return usrp_9862_read (d_udh, which_codec, regno, value); -} - -int -usrp_basic::_read_9862 (int which_codec, int regno) const -{ - unsigned char value; - if (!_read_9862 (which_codec, regno, &value)) - return READ_FAILED; - return value; -} - -bool -usrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf) -{ - return usrp_spi_write (d_udh, optional_header, enables, format, - buf.data(), buf.size()); -} - -std::string -usrp_basic::_read_spi (int optional_header, int enables, int format, int len) -{ - if (len <= 0) - return ""; - - char buf[len]; - - if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len)) - return ""; - - return std::string (buf, len); -} - - -bool -usrp_basic::_set_led (int which_led, bool on) -{ - return usrp_set_led (d_udh, which_led, on); -} - -bool -usrp_basic::write_atr_tx_delay(int value) -{ - return _write_fpga_reg(FR_ATR_TX_DELAY, value); -} - -bool -usrp_basic::write_atr_rx_delay(int value) -{ - return _write_fpga_reg(FR_ATR_RX_DELAY, value); -} - -/* - * ---------------------------------------------------------------- - * Routines to access and control daughterboard specific i/o - * ---------------------------------------------------------------- - */ -static int -slot_id_to_oe_reg (int slot_id) -{ - static int reg[4] = { FR_OE_0, FR_OE_1, FR_OE_2, FR_OE_3 }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -slot_id_to_io_reg (int slot_id) -{ - static int reg[4] = { FR_IO_0, FR_IO_1, FR_IO_2, FR_IO_3 }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -slot_id_to_refclk_reg(int slot_id) -{ - static int reg[4] = { FR_TX_A_REFCLK, FR_RX_A_REFCLK, FR_TX_B_REFCLK, FR_RX_B_REFCLK }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -slot_id_to_atr_mask_reg(int slot_id) -{ - static int reg[4] = { FR_ATR_MASK_0, FR_ATR_MASK_1, FR_ATR_MASK_2, FR_ATR_MASK_3 }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -slot_id_to_atr_txval_reg(int slot_id) -{ - static int reg[4] = { FR_ATR_TXVAL_0, FR_ATR_TXVAL_1, FR_ATR_TXVAL_2, FR_ATR_TXVAL_3 }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -slot_id_to_atr_rxval_reg(int slot_id) -{ - static int reg[4] = { FR_ATR_RXVAL_0, FR_ATR_RXVAL_1, FR_ATR_RXVAL_2, FR_ATR_RXVAL_3 }; - assert (0 <= slot_id && slot_id < 4); - return reg[slot_id]; -} - -static int -to_slot(txrx_t txrx, int which_side) -{ - // TX_A = 0 - // RX_A = 1 - // TX_B = 2 - // RX_B = 3 - return ((which_side & 0x1) << 1) | ((txrx & 0x1) == C_RX); -} - -bool -usrp_basic::common_set_pga(txrx_t txrx, int which_amp, double gain) -{ - if (which_amp < 0 || which_amp > 3) - return false; - - gain = std::min(common_pga_max(txrx), - std::max(common_pga_min(txrx), gain)); - - int codec = which_amp >> 1; - int int_gain = (int) rint((gain - common_pga_min(txrx)) / common_pga_db_per_step(txrx)); - - if (txrx == C_TX){ // 0 and 1 are same, as are 2 and 3 - return _write_9862(codec, REG_TX_PGA, int_gain); - } - else { - int reg = (which_amp & 1) == 0 ? REG_RX_A : REG_RX_B; - - // read current value to get input buffer bypass flag. - unsigned char cur_rx; - if (!_read_9862(codec, reg, &cur_rx)) - return false; - - cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f); - return _write_9862(codec, reg, cur_rx); - } -} - -double -usrp_basic::common_pga(txrx_t txrx, int which_amp) const -{ - if (which_amp < 0 || which_amp > 3) - return READ_FAILED; - - if (txrx == C_TX){ - int codec = which_amp >> 1; - unsigned char v; - bool ok = _read_9862 (codec, REG_TX_PGA, &v); - if (!ok) - return READ_FAILED; - - return (pga_db_per_step() * v) + pga_min(); - } - else { - int codec = which_amp >> 1; - int reg = (which_amp & 1) == 0 ? REG_RX_A : REG_RX_B; - unsigned char v; - bool ok = _read_9862 (codec, reg, &v); - if (!ok) - return READ_FAILED; - - return (pga_db_per_step() * (v & 0x1f)) + pga_min(); - } -} - -double -usrp_basic::common_pga_min(txrx_t txrx) const -{ - if (txrx == C_TX) - return -20.0; - else - return 0.0; -} - -double -usrp_basic::common_pga_max(txrx_t txrx) const -{ - if (txrx == C_TX) - return 0.0; - else - return 20.0; -} - -double -usrp_basic::common_pga_db_per_step(txrx_t txrx) const -{ - if (txrx == C_TX) - return 20.0 / 255; - else - return 20.0 / 20; -} - -bool -usrp_basic::_common_write_oe(txrx_t txrx, int which_side, int value, int mask) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_oe_reg(to_slot(txrx, which_side)), - (mask << 16) | (value & 0xffff)); -} - -bool -usrp_basic::common_write_io(txrx_t txrx, int which_side, int value, int mask) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_io_reg(to_slot(txrx, which_side)), - (mask << 16) | (value & 0xffff)); -} - -bool -usrp_basic::common_read_io(txrx_t txrx, int which_side, int *value) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - int t; - int reg = which_side + 1; // FIXME, *very* magic number (fix in serial_io.v) - bool ok = _read_fpga_reg(reg, &t); - if (!ok) - return false; - - if (txrx == C_TX){ - *value = t & 0xffff; // FIXME, more magic - return true; - } - else { - *value = (t >> 16) & 0xffff; // FIXME, more magic - return true; - } -} - -int -usrp_basic::common_read_io(txrx_t txrx, int which_side) -{ - int value; - if (!common_read_io(txrx, which_side, &value)) - return READ_FAILED; - return value; -} - -bool -usrp_basic::common_write_refclk(txrx_t txrx, int which_side, int value) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_refclk_reg(to_slot(txrx, which_side)), - value); -} - -bool -usrp_basic::common_write_atr_mask(txrx_t txrx, int which_side, int value) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_atr_mask_reg(to_slot(txrx, which_side)), - value); -} - -bool -usrp_basic::common_write_atr_txval(txrx_t txrx, int which_side, int value) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_atr_txval_reg(to_slot(txrx, which_side)), - value); -} - -bool -usrp_basic::common_write_atr_rxval(txrx_t txrx, int which_side, int value) -{ - if (! (0 <= which_side && which_side <= 1)) - return false; - - return _write_fpga_reg(slot_id_to_atr_rxval_reg(to_slot(txrx, which_side)), - value); -} - -bool -usrp_basic::common_write_aux_dac(txrx_t txrx, int which_side, int which_dac, int value) -{ - return _write_aux_dac(to_slot(txrx, which_side), which_dac, value); -} - -bool -usrp_basic::common_read_aux_adc(txrx_t txrx, int which_side, int which_adc, int *value) -{ - return _read_aux_adc(to_slot(txrx, which_side), which_adc, value); -} - -int -usrp_basic::common_read_aux_adc(txrx_t txrx, int which_side, int which_adc) -{ - return _read_aux_adc(to_slot(txrx, which_side), which_adc); -} - - -//////////////////////////////////////////////////////////////// -// -// usrp_basic_rx -// -//////////////////////////////////////////////////////////////// - -static unsigned char rx_init_regs[] = { - REG_RX_PWR_DN, 0, - REG_RX_A, 0, // minimum gain = 0x00 (max gain = 0x14) - REG_RX_B, 0, // minimum gain = 0x00 (max gain = 0x14) - REG_RX_MISC, (RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY), - REG_RX_IF, (RX_IF_USE_CLKOUT1 - | RX_IF_2S_COMP), - REG_RX_DIGITAL, (RX_DIGITAL_2_CHAN) -}; - - -usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename - ) - : usrp_basic (which_board, open_rx_interface, fpga_filename, firmware_filename), - d_devhandle (0), d_ephandle (0), - d_bytes_seen (0), d_first_read (true), - d_rx_enable (false) -{ - // initialize rx specific registers - - if (!usrp_9862_write_many_all (d_udh, rx_init_regs, sizeof (rx_init_regs))){ - fprintf (stderr, "usrp_basic_rx: failed to init AD9862 RX regs\n"); - throw std::runtime_error ("usrp_basic_rx/init_9862"); - } - - if (0){ - // FIXME power down 2nd codec rx path - usrp_9862_write (d_udh, 1, REG_RX_PWR_DN, 0x1); // power down everything - } - - // Reset the rx path and leave it disabled. - set_rx_enable (false); - usrp_set_fpga_rx_reset (d_udh, true); - usrp_set_fpga_rx_reset (d_udh, false); - - set_fpga_rx_sample_rate_divisor (2); // usually correct - - set_dc_offset_cl_enable(0xf, 0xf); // enable DC offset removal control loops - - probe_rx_slots (false); - - //d_db[0] = instantiate_dbs(d_dbid[0], this, 0); - //d_db[1] = instantiate_dbs(d_dbid[1], this, 1); - - // check fusb buffering parameters - - if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) - throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); - - if (fusb_nblocks < 0) - throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); - - if (fusb_block_size == 0) - fusb_block_size = fusb_sysconfig::default_block_size(); - - if (fusb_nblocks == 0) - fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); - - d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); - d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true, - fusb_block_size, fusb_nblocks); - - write_atr_mask(0, 0); // zero Rx A Auto Transmit/Receive regs - write_atr_txval(0, 0); - write_atr_rxval(0, 0); - write_atr_mask(1, 0); // zero Rx B Auto Transmit/Receive regs - write_atr_txval(1, 0); - write_atr_rxval(1, 0); -} - -static unsigned char rx_fini_regs[] = { - REG_RX_PWR_DN, 0x1 // power down everything -}; - -usrp_basic_rx::~usrp_basic_rx () -{ - if (!set_rx_enable (false)){ - fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n"); - } - - d_ephandle->stop (); - delete d_ephandle; - delete d_devhandle; - - if (!usrp_9862_write_many_all (d_udh, rx_fini_regs, sizeof (rx_fini_regs))){ - fprintf (stderr, "usrp_basic_rx: failed to fini AD9862 RX regs\n"); - } - - shutdown_daughterboards(); -} - - -bool -usrp_basic_rx::start () -{ - if (!usrp_basic::start ()) // invoke parent's method - return false; - - // fire off reads before asserting rx_enable - - if (!d_ephandle->start ()){ - fprintf (stderr, "usrp_basic_rx: failed to start end point streaming"); - return false; - } - - if (!set_rx_enable (true)){ - fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); - return false; - } - - return true; -} - -bool -usrp_basic_rx::stop () -{ - bool ok = usrp_basic::stop(); - - if (!set_rx_enable(false)){ - fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n"); - ok = false; - } - - if (!d_ephandle->stop()){ - fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming"); - ok = false; - } - - return ok; -} - -usrp_basic_rx * -usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename) -{ - usrp_basic_rx *u = 0; - - try { - u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename); - return u; - } - catch (...){ - delete u; - return 0; - } - - return u; -} - -bool -usrp_basic_rx::set_fpga_rx_sample_rate_divisor (unsigned int div) -{ - return _write_fpga_reg (FR_RX_SAMPLE_RATE_DIV, div - 1); -} - - -/* - * \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 -usrp_basic_rx::read (void *buf, int len, bool *overrun) -{ - int r; - - if (overrun) - *overrun = false; - - if (len < 0 || (len % 512) != 0){ - fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len); - return -1; - } - - r = d_ephandle->read (buf, len); - if (r > 0) - d_bytes_seen += r; - - /* - * In many cases, the FPGA reports an rx overrun right after we - * enable the Rx path. If this is our first read, check for the - * overrun to clear the condition, then ignore the result. - */ - if (0 && d_first_read){ // FIXME - d_first_read = false; - bool bogus_overrun; - usrp_check_rx_overrun (d_udh, &bogus_overrun); - } - - if (overrun != 0 && d_bytes_seen >= d_bytes_per_poll){ - d_bytes_seen = 0; - if (!usrp_check_rx_overrun (d_udh, overrun)){ - fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n"); - } - } - - return r; -} - -bool -usrp_basic_rx::set_rx_enable (bool on) -{ - d_rx_enable = on; - return usrp_set_fpga_rx_enable (d_udh, on); -} - -// conditional disable, return prev state -bool -usrp_basic_rx::disable_rx () -{ - bool enabled = rx_enable (); - if (enabled) - set_rx_enable (false); - return enabled; -} - -// conditional set -void -usrp_basic_rx::restore_rx (bool on) -{ - if (on != rx_enable ()) - set_rx_enable (on); -} - -void -usrp_basic_rx::probe_rx_slots (bool verbose) -{ - struct usrp_dboard_eeprom eeprom; - static int slot_id_map[2] = { SLOT_RX_A, SLOT_RX_B }; - static const char *slot_name[2] = { "RX d'board A", "RX d'board B" }; - - for (int i = 0; i < 2; i++){ - int slot_id = slot_id_map [i]; - const char *msg = 0; - usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); - - switch (s){ - case UDBE_OK: - d_dbid[i] = eeprom.id; - msg = usrp_dbid_to_string (eeprom.id).c_str (); - set_adc_offset (2*i+0, eeprom.offset[0]); - set_adc_offset (2*i+1, eeprom.offset[1]); - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_NO_EEPROM: - d_dbid[i] = -1; - msg = ""; - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_INVALID_EEPROM: - d_dbid[i] = -2; - msg = "Invalid EEPROM contents"; - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_BAD_SLOT: - default: - assert (0); - } - - if (verbose){ - fflush (stdout); - fprintf (stderr, "%s: %s\n", slot_name[i], msg); - } - } -} - -bool -usrp_basic_rx::set_pga (int which_amp, double gain) -{ - return common_set_pga(C_RX, which_amp, gain); -} - -double -usrp_basic_rx::pga(int which_amp) const -{ - return common_pga(C_RX, which_amp); -} - -double -usrp_basic_rx::pga_min() const -{ - return common_pga_min(C_RX); -} - -double -usrp_basic_rx::pga_max() const -{ - return common_pga_max(C_RX); -} - -double -usrp_basic_rx::pga_db_per_step() const -{ - return common_pga_db_per_step(C_RX); -} - -bool -usrp_basic_rx::_write_oe (int which_side, int value, int mask) -{ - return _common_write_oe(C_RX, which_side, value, mask); -} - -bool -usrp_basic_rx::write_io (int which_side, int value, int mask) -{ - return common_write_io(C_RX, which_side, value, mask); -} - -bool -usrp_basic_rx::read_io (int which_side, int *value) -{ - return common_read_io(C_RX, which_side, value); -} - -int -usrp_basic_rx::read_io (int which_side) -{ - return common_read_io(C_RX, which_side); -} - -bool -usrp_basic_rx::write_refclk(int which_side, int value) -{ - return common_write_refclk(C_RX, which_side, value); -} - -bool -usrp_basic_rx::write_atr_mask(int which_side, int value) -{ - return common_write_atr_mask(C_RX, which_side, value); -} - -bool -usrp_basic_rx::write_atr_txval(int which_side, int value) -{ - return common_write_atr_txval(C_RX, which_side, value); -} - -bool -usrp_basic_rx::write_atr_rxval(int which_side, int value) -{ - return common_write_atr_rxval(C_RX, which_side, value); -} - -bool -usrp_basic_rx::write_aux_dac (int which_side, int which_dac, int value) -{ - return common_write_aux_dac(C_RX, which_side, which_dac, value); -} - -bool -usrp_basic_rx::read_aux_adc (int which_side, int which_adc, int *value) -{ - return common_read_aux_adc(C_RX, which_side, which_adc, value); -} - -int -usrp_basic_rx::read_aux_adc (int which_side, int which_adc) -{ - return common_read_aux_adc(C_RX, which_side, which_adc); -} - -int -usrp_basic_rx::block_size () const { return d_ephandle->block_size(); } - -//////////////////////////////////////////////////////////////// -// -// usrp_basic_tx -// -//////////////////////////////////////////////////////////////// - - -// -// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz -// DAC input is latched on rising edge of CLKOUT2 -// NCO is disabled -// interpolate 2x -// coarse modulator disabled -// - -static unsigned char tx_init_regs[] = { - REG_TX_PWR_DN, 0, - REG_TX_A_OFFSET_LO, 0, - REG_TX_A_OFFSET_HI, 0, - REG_TX_B_OFFSET_LO, 0, - REG_TX_B_OFFSET_HI, 0, - REG_TX_A_GAIN, (TX_X_GAIN_COARSE_FULL | 0), - REG_TX_B_GAIN, (TX_X_GAIN_COARSE_FULL | 0), - REG_TX_PGA, 0xff, // maximum gain (0 dB) - REG_TX_MISC, 0, - REG_TX_IF, (TX_IF_USE_CLKOUT1 - | TX_IF_I_FIRST - | TX_IF_INV_TX_SYNC - | TX_IF_2S_COMP - | TX_IF_INTERLEAVED), - REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS - | TX_DIGITAL_INTERPOLATE_4X), - REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO - | TX_MODULATOR_COARSE_MODULATION_NONE), - REG_TX_NCO_FTW_7_0, 0, - REG_TX_NCO_FTW_15_8, 0, - REG_TX_NCO_FTW_23_16, 0 -}; - -usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename) - : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename), - d_devhandle (0), d_ephandle (0), - d_bytes_seen (0), d_first_write (true), - d_tx_enable (false) -{ - if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){ - fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n"); - throw std::runtime_error ("usrp_basic_tx/init_9862"); - } - - if (0){ - // FIXME power down 2nd codec tx path - usrp_9862_write (d_udh, 1, REG_TX_PWR_DN, - (TX_PWR_DN_TX_DIGITAL - | TX_PWR_DN_TX_ANALOG_BOTH)); - } - - // Reset the tx path and leave it disabled. - set_tx_enable (false); - usrp_set_fpga_tx_reset (d_udh, true); - usrp_set_fpga_tx_reset (d_udh, false); - - set_fpga_tx_sample_rate_divisor (4); // we're using interp x4 - - probe_tx_slots (false); - - //d_db[0] = instantiate_dbs(d_dbid[0], this, 0); - //d_db[1] = instantiate_dbs(d_dbid[1], this, 1); - - // check fusb buffering parameters - - if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) - throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); - - if (fusb_nblocks < 0) - throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); - - if (fusb_block_size == 0) - fusb_block_size = FUSB_BLOCK_SIZE; - - if (fusb_nblocks == 0) - fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); - - d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); - d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false, - fusb_block_size, fusb_nblocks); - - write_atr_mask(0, 0); // zero Tx A Auto Transmit/Receive regs - write_atr_txval(0, 0); - write_atr_rxval(0, 0); - write_atr_mask(1, 0); // zero Tx B Auto Transmit/Receive regs - write_atr_txval(1, 0); - write_atr_rxval(1, 0); -} - - -static unsigned char tx_fini_regs[] = { - REG_TX_PWR_DN, (TX_PWR_DN_TX_DIGITAL - | TX_PWR_DN_TX_ANALOG_BOTH), - REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO - | TX_MODULATOR_COARSE_MODULATION_NONE) -}; - -usrp_basic_tx::~usrp_basic_tx () -{ - d_ephandle->stop (); - delete d_ephandle; - delete d_devhandle; - - if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){ - fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n"); - } - - shutdown_daughterboards(); -} - -bool -usrp_basic_tx::start () -{ - if (!usrp_basic::start ()) - return false; - - if (!set_tx_enable (true)){ - fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); - return false; - } - - if (!d_ephandle->start ()){ - fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); - return false; - } - - return true; -} - -bool -usrp_basic_tx::stop () -{ - bool ok = usrp_basic::stop (); - - if (!d_ephandle->stop ()){ - fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming"); - ok = false; - } - - if (!set_tx_enable (false)){ - fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n"); - ok = false; - } - - return ok; -} - -usrp_basic_tx * -usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks, - const std::string fpga_filename, - const std::string firmware_filename) -{ - usrp_basic_tx *u = 0; - - try { - u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, - fpga_filename, firmware_filename); - return u; - } - catch (...){ - delete u; - return 0; - } - - return u; -} - -bool -usrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div) -{ - return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1); -} - -/*! - * \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 -usrp_basic_tx::write (const void *buf, int len, bool *underrun) -{ - int r; - - if (underrun) - *underrun = false; - - if (len < 0 || (len % 512) != 0){ - fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len); - return -1; - } - - r = d_ephandle->write (buf, len); - if (r > 0) - d_bytes_seen += r; - - /* - * In many cases, the FPGA reports an tx underrun right after we - * enable the Tx path. If this is our first write, check for the - * underrun to clear the condition, then ignore the result. - */ - if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){ - d_first_write = false; - bool bogus_underrun; - usrp_check_tx_underrun (d_udh, &bogus_underrun); - } - - if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){ - d_bytes_seen = 0; - if (!usrp_check_tx_underrun (d_udh, underrun)){ - fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n"); - } - } - - return r; -} - -void -usrp_basic_tx::wait_for_completion () -{ - d_ephandle->wait_for_completion (); -} - -bool -usrp_basic_tx::set_tx_enable (bool on) -{ - d_tx_enable = on; - // fprintf (stderr, "set_tx_enable %d\n", on); - return usrp_set_fpga_tx_enable (d_udh, on); -} - -// conditional disable, return prev state -bool -usrp_basic_tx::disable_tx () -{ - bool enabled = tx_enable (); - if (enabled) - set_tx_enable (false); - return enabled; -} - -// conditional set -void -usrp_basic_tx::restore_tx (bool on) -{ - if (on != tx_enable ()) - set_tx_enable (on); -} - -void -usrp_basic_tx::probe_tx_slots (bool verbose) -{ - struct usrp_dboard_eeprom eeprom; - static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B }; - static const char *slot_name[2] = { "TX d'board A", "TX d'board B" }; - - for (int i = 0; i < 2; i++){ - int slot_id = slot_id_map [i]; - const char *msg = 0; - usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); - - switch (s){ - case UDBE_OK: - d_dbid[i] = eeprom.id; - msg = usrp_dbid_to_string (eeprom.id).c_str (); - // FIXME, figure out interpretation of dc offset for TX d'boards - // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff); - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_NO_EEPROM: - d_dbid[i] = -1; - msg = ""; - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_INVALID_EEPROM: - d_dbid[i] = -2; - msg = "Invalid EEPROM contents"; - _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); - _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); - break; - - case UDBE_BAD_SLOT: - default: - assert (0); - } - - if (verbose){ - fflush (stdout); - fprintf (stderr, "%s: %s\n", slot_name[i], msg); - } - } -} - -bool -usrp_basic_tx::set_pga (int which_amp, double gain) -{ - return common_set_pga(C_TX, which_amp, gain); -} - -double -usrp_basic_tx::pga (int which_amp) const -{ - return common_pga(C_TX, which_amp); -} - -double -usrp_basic_tx::pga_min() const -{ - return common_pga_min(C_TX); -} - -double -usrp_basic_tx::pga_max() const -{ - return common_pga_max(C_TX); -} - -double -usrp_basic_tx::pga_db_per_step() const -{ - return common_pga_db_per_step(C_TX); -} - -bool -usrp_basic_tx::_write_oe (int which_side, int value, int mask) -{ - return _common_write_oe(C_TX, which_side, value, mask); -} - -bool -usrp_basic_tx::write_io (int which_side, int value, int mask) -{ - return common_write_io(C_TX, which_side, value, mask); -} - -bool -usrp_basic_tx::read_io (int which_side, int *value) -{ - return common_read_io(C_TX, which_side, value); -} - -int -usrp_basic_tx::read_io (int which_side) -{ - return common_read_io(C_TX, which_side); -} - -bool -usrp_basic_tx::write_refclk(int which_side, int value) -{ - return common_write_refclk(C_TX, which_side, value); -} - -bool -usrp_basic_tx::write_atr_mask(int which_side, int value) -{ - return common_write_atr_mask(C_TX, which_side, value); -} - -bool -usrp_basic_tx::write_atr_txval(int which_side, int value) -{ - return common_write_atr_txval(C_TX, which_side, value); -} - -bool -usrp_basic_tx::write_atr_rxval(int which_side, int value) -{ - return common_write_atr_rxval(C_TX, which_side, value); -} - -bool -usrp_basic_tx::write_aux_dac (int which_side, int which_dac, int value) -{ - return common_write_aux_dac(C_TX, which_side, which_dac, value); -} - -bool -usrp_basic_tx::read_aux_adc (int which_side, int which_adc, int *value) -{ - return common_read_aux_adc(C_TX, which_side, which_adc, value); -} - -int -usrp_basic_tx::read_aux_adc (int which_side, int which_adc) -{ - return common_read_aux_adc(C_TX, which_side, which_adc); -} - -int -usrp_basic_tx::block_size () const { return d_ephandle->block_size(); } - diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc new file mode 100644 index 000000000..2579827e9 --- /dev/null +++ b/usrp/host/lib/usrp_basic_common.cc @@ -0,0 +1,1481 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "usrp/usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include "fusb.h" +#include "db_boards.h" +#include +#include +#include +#include +#include +#include + +#if 1 +#include +#else +#include +#endif + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// These set the buffer size used for each end point using the fast +// usb interface. The kernel ends up locking down this much memory. + +static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); +static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; + + +static const double POLLING_INTERVAL = 0.1; // seconds + +//////////////////////////////////////////////////////////////// + +static libusb_device_handle * +open_rx_interface (libusb_device *dev) +{ + libusb_device_handle *udh = usrp_open_rx_interface (dev); + if (udh == 0){ + fprintf (stderr, "usrp_basic_rx: can't open rx interface\n"); + } + return udh; +} + +static libusb_device_handle * +open_tx_interface (libusb_device *dev) +{ + libusb_device_handle *udh = usrp_open_tx_interface (dev); + if (udh == 0){ + fprintf (stderr, "usrp_basic_tx: can't open tx interface\n"); + } + return udh; +} + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// These settings give us: +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + +void +usrp_basic::shutdown_daughterboards() +{ + // nuke d'boards before we close down USB in ~usrp_basic + // shutdown() will do any board shutdown while the USRP can still + // be talked to + for(size_t i = 0; i < d_db.size(); i++) + for(size_t j = 0; j < d_db[i].size(); j++) + d_db[i][j]->shutdown(); +} + +void +usrp_basic::init_db(usrp_basic_sptr u) +{ + if (u.get() != this) + throw std::invalid_argument("u is not this"); + + d_db[0] = instantiate_dbs(d_dbid[0], u, 0); + d_db[1] = instantiate_dbs(d_dbid[1], u, 1); +} + +std::vector +usrp_basic::db(int which_side) +{ + which_side &= 0x1; // clamp it to avoid any reporting any errors + return d_db[which_side]; +} + +bool +usrp_basic::is_valid(const usrp_subdev_spec &ss) +{ + if (ss.side < 0 || ss.side > 1) + return false; + + if (ss.subdev < 0 || ss.subdev >= d_db[ss.side].size()) + return false; + + return true; +} + +db_base_sptr +usrp_basic::selected_subdev(const usrp_subdev_spec &ss) +{ + if (!is_valid(ss)) + throw std::invalid_argument("invalid subdev_spec"); + + return d_db[ss.side][ss.subdev]; +} + +bool +usrp_basic::start () +{ + return true; // nop +} + +bool +usrp_basic::stop () +{ + return true; // nop +} + +void +usrp_basic::set_usb_data_rate (int usb_data_rate) +{ + d_usb_data_rate = usb_data_rate; + d_bytes_per_poll = (int) (usb_data_rate * POLLING_INTERVAL); +} + +bool +usrp_basic::_write_aux_dac (int slot, int which_dac, int value) +{ + return usrp_write_aux_dac (d_udh, slot, which_dac, value); +} + +bool +usrp_basic::_read_aux_adc (int slot, int which_adc, int *value) +{ + return usrp_read_aux_adc (d_udh, slot, which_adc, value); +} + +int +usrp_basic::_read_aux_adc (int slot, int which_adc) +{ + int value; + if (!_read_aux_adc (slot, which_adc, &value)) + return READ_FAILED; + + return value; +} + +bool +usrp_basic::write_eeprom (int i2c_addr, int eeprom_offset, const std::string buf) +{ + return usrp_eeprom_write (d_udh, i2c_addr, eeprom_offset, buf.data (), buf.size ()); +} + +std::string +usrp_basic::read_eeprom (int i2c_addr, int eeprom_offset, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_eeprom_read (d_udh, i2c_addr, eeprom_offset, buf, len)) + return ""; + + return std::string (buf, len); +} + +bool +usrp_basic::write_i2c (int i2c_addr, const std::string buf) +{ + return usrp_i2c_write (d_udh, i2c_addr, buf.data (), buf.size ()); +} + +std::string +usrp_basic::read_i2c (int i2c_addr, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_i2c_read (d_udh, i2c_addr, buf, len)) + return ""; + + return std::string (buf, len); +} + +std::string +usrp_basic::serial_number() +{ + return usrp_serial_number(d_udh); +} + +// ---------------------------------------------------------------- + +bool +usrp_basic::set_adc_offset (int which_adc, int offset) +{ + if (which_adc < 0 || which_adc > 3) + return false; + + return _write_fpga_reg (FR_ADC_OFFSET_0 + which_adc, offset); +} + +bool +usrp_basic::set_dac_offset (int which_dac, int offset, int offset_pin) +{ + if (which_dac < 0 || which_dac > 3) + return false; + + int which_codec = which_dac >> 1; + int tx_a = (which_dac & 0x1) == 0; + int lo = ((offset & 0x3) << 6) | (offset_pin & 0x1); + int hi = (offset >> 2); + bool ok; + + if (tx_a){ + ok = _write_9862 (which_codec, REG_TX_A_OFFSET_LO, lo); + ok &= _write_9862 (which_codec, REG_TX_A_OFFSET_HI, hi); + } + else { + ok = _write_9862 (which_codec, REG_TX_B_OFFSET_LO, lo); + ok &= _write_9862 (which_codec, REG_TX_B_OFFSET_HI, hi); + } + return ok; +} + +bool +usrp_basic::set_adc_buffer_bypass (int which_adc, bool bypass) +{ + if (which_adc < 0 || which_adc > 3) + return false; + + int codec = which_adc >> 1; + int reg = (which_adc & 1) == 0 ? REG_RX_A : REG_RX_B; + + unsigned char cur_rx; + unsigned char cur_pwr_dn; + + // If the input buffer is bypassed, we need to power it down too. + + bool ok = _read_9862 (codec, reg, &cur_rx); + ok &= _read_9862 (codec, REG_RX_PWR_DN, &cur_pwr_dn); + if (!ok) + return false; + + if (bypass){ + cur_rx |= RX_X_BYPASS_INPUT_BUFFER; + cur_pwr_dn |= ((which_adc & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B; + } + else { + cur_rx &= ~RX_X_BYPASS_INPUT_BUFFER; + cur_pwr_dn &= ~(((which_adc & 1) == 0) ? RX_PWR_DN_BUF_A : RX_PWR_DN_BUF_B); + } + + ok &= _write_9862 (codec, reg, cur_rx); + ok &= _write_9862 (codec, REG_RX_PWR_DN, cur_pwr_dn); + return ok; +} + +bool +usrp_basic::set_dc_offset_cl_enable(int bits, int mask) +{ + return _write_fpga_reg(FR_DC_OFFSET_CL_EN, + (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask)); +} + +// ---------------------------------------------------------------- + +bool +usrp_basic::_write_fpga_reg (int regno, int value) +{ + if (d_verbose){ + fprintf (stdout, "_write_fpga_reg(%3d, 0x%08x)\n", regno, value); + fflush (stdout); + } + + if (regno >= 0 && regno < MAX_REGS) + d_fpga_shadows[regno] = value; + + return usrp_write_fpga_reg (d_udh, regno, value); +} + +bool +usrp_basic::_write_fpga_reg_masked (int regno, int value, int mask) +{ + //Only use this for registers who actually use a mask in the verilog firmware, like FR_RX_MASTER_SLAVE + //value is a 16 bits value and mask is a 16 bits mask + if (d_verbose){ + fprintf (stdout, "_write_fpga_reg_masked(%3d, 0x%04x,0x%04x)\n", regno, value, mask); + fflush (stdout); + } + + if (regno >= 0 && regno < MAX_REGS) + d_fpga_shadows[regno] = value; + + return usrp_write_fpga_reg (d_udh, regno, (value & 0xffff) | ((mask & 0xffff)<<16)); +} + + +bool +usrp_basic::_read_fpga_reg (int regno, int *value) +{ + return usrp_read_fpga_reg (d_udh, regno, value); +} + +int +usrp_basic::_read_fpga_reg (int regno) +{ + int value; + if (!_read_fpga_reg (regno, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic::_write_9862 (int which_codec, int regno, unsigned char value) +{ + if (0 && d_verbose){ + // FIXME really want to enable logging in usrp_prims:usrp_9862_write + fprintf(stdout, "_write_9862(codec = %d, regno = %2d, val = 0x%02x)\n", which_codec, regno, value); + fflush(stdout); + } + + return usrp_9862_write (d_udh, which_codec, regno, value); +} + + +bool +usrp_basic::_read_9862 (int which_codec, int regno, unsigned char *value) const +{ + return usrp_9862_read (d_udh, which_codec, regno, value); +} + +int +usrp_basic::_read_9862 (int which_codec, int regno) const +{ + unsigned char value; + if (!_read_9862 (which_codec, regno, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic::_write_spi (int optional_header, int enables, int format, std::string buf) +{ + return usrp_spi_write (d_udh, optional_header, enables, format, + buf.data(), buf.size()); +} + +std::string +usrp_basic::_read_spi (int optional_header, int enables, int format, int len) +{ + if (len <= 0) + return ""; + + char buf[len]; + + if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len)) + return ""; + + return std::string (buf, len); +} + + +bool +usrp_basic::_set_led (int which_led, bool on) +{ + return usrp_set_led (d_udh, which_led, on); +} + +bool +usrp_basic::write_atr_tx_delay(int value) +{ + return _write_fpga_reg(FR_ATR_TX_DELAY, value); +} + +bool +usrp_basic::write_atr_rx_delay(int value) +{ + return _write_fpga_reg(FR_ATR_RX_DELAY, value); +} + +/* + * ---------------------------------------------------------------- + * Routines to access and control daughterboard specific i/o + * ---------------------------------------------------------------- + */ +static int +slot_id_to_oe_reg (int slot_id) +{ + static int reg[4] = { FR_OE_0, FR_OE_1, FR_OE_2, FR_OE_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_io_reg (int slot_id) +{ + static int reg[4] = { FR_IO_0, FR_IO_1, FR_IO_2, FR_IO_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_refclk_reg(int slot_id) +{ + static int reg[4] = { FR_TX_A_REFCLK, FR_RX_A_REFCLK, FR_TX_B_REFCLK, FR_RX_B_REFCLK }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_atr_mask_reg(int slot_id) +{ + static int reg[4] = { FR_ATR_MASK_0, FR_ATR_MASK_1, FR_ATR_MASK_2, FR_ATR_MASK_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_atr_txval_reg(int slot_id) +{ + static int reg[4] = { FR_ATR_TXVAL_0, FR_ATR_TXVAL_1, FR_ATR_TXVAL_2, FR_ATR_TXVAL_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +slot_id_to_atr_rxval_reg(int slot_id) +{ + static int reg[4] = { FR_ATR_RXVAL_0, FR_ATR_RXVAL_1, FR_ATR_RXVAL_2, FR_ATR_RXVAL_3 }; + assert (0 <= slot_id && slot_id < 4); + return reg[slot_id]; +} + +static int +to_slot(txrx_t txrx, int which_side) +{ + // TX_A = 0 + // RX_A = 1 + // TX_B = 2 + // RX_B = 3 + return ((which_side & 0x1) << 1) | ((txrx & 0x1) == C_RX); +} + +bool +usrp_basic::common_set_pga(txrx_t txrx, int which_amp, double gain) +{ + if (which_amp < 0 || which_amp > 3) + return false; + + gain = std::min(common_pga_max(txrx), + std::max(common_pga_min(txrx), gain)); + + int codec = which_amp >> 1; + int int_gain = (int) rint((gain - common_pga_min(txrx)) / common_pga_db_per_step(txrx)); + + if (txrx == C_TX){ // 0 and 1 are same, as are 2 and 3 + return _write_9862(codec, REG_TX_PGA, int_gain); + } + else { + int reg = (which_amp & 1) == 0 ? REG_RX_A : REG_RX_B; + + // read current value to get input buffer bypass flag. + unsigned char cur_rx; + if (!_read_9862(codec, reg, &cur_rx)) + return false; + + cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f); + return _write_9862(codec, reg, cur_rx); + } +} + +double +usrp_basic::common_pga(txrx_t txrx, int which_amp) const +{ + if (which_amp < 0 || which_amp > 3) + return READ_FAILED; + + if (txrx == C_TX){ + int codec = which_amp >> 1; + unsigned char v; + bool ok = _read_9862 (codec, REG_TX_PGA, &v); + if (!ok) + return READ_FAILED; + + return (pga_db_per_step() * v) + pga_min(); + } + else { + int codec = which_amp >> 1; + int reg = (which_amp & 1) == 0 ? REG_RX_A : REG_RX_B; + unsigned char v; + bool ok = _read_9862 (codec, reg, &v); + if (!ok) + return READ_FAILED; + + return (pga_db_per_step() * (v & 0x1f)) + pga_min(); + } +} + +double +usrp_basic::common_pga_min(txrx_t txrx) const +{ + if (txrx == C_TX) + return -20.0; + else + return 0.0; +} + +double +usrp_basic::common_pga_max(txrx_t txrx) const +{ + if (txrx == C_TX) + return 0.0; + else + return 20.0; +} + +double +usrp_basic::common_pga_db_per_step(txrx_t txrx) const +{ + if (txrx == C_TX) + return 20.0 / 255; + else + return 20.0 / 20; +} + +bool +usrp_basic::_common_write_oe(txrx_t txrx, int which_side, int value, int mask) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_oe_reg(to_slot(txrx, which_side)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic::common_write_io(txrx_t txrx, int which_side, int value, int mask) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_io_reg(to_slot(txrx, which_side)), + (mask << 16) | (value & 0xffff)); +} + +bool +usrp_basic::common_read_io(txrx_t txrx, int which_side, int *value) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + int t; + int reg = which_side + 1; // FIXME, *very* magic number (fix in serial_io.v) + bool ok = _read_fpga_reg(reg, &t); + if (!ok) + return false; + + if (txrx == C_TX){ + *value = t & 0xffff; // FIXME, more magic + return true; + } + else { + *value = (t >> 16) & 0xffff; // FIXME, more magic + return true; + } +} + +int +usrp_basic::common_read_io(txrx_t txrx, int which_side) +{ + int value; + if (!common_read_io(txrx, which_side, &value)) + return READ_FAILED; + return value; +} + +bool +usrp_basic::common_write_refclk(txrx_t txrx, int which_side, int value) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_refclk_reg(to_slot(txrx, which_side)), + value); +} + +bool +usrp_basic::common_write_atr_mask(txrx_t txrx, int which_side, int value) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_atr_mask_reg(to_slot(txrx, which_side)), + value); +} + +bool +usrp_basic::common_write_atr_txval(txrx_t txrx, int which_side, int value) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_atr_txval_reg(to_slot(txrx, which_side)), + value); +} + +bool +usrp_basic::common_write_atr_rxval(txrx_t txrx, int which_side, int value) +{ + if (! (0 <= which_side && which_side <= 1)) + return false; + + return _write_fpga_reg(slot_id_to_atr_rxval_reg(to_slot(txrx, which_side)), + value); +} + +bool +usrp_basic::common_write_aux_dac(txrx_t txrx, int which_side, int which_dac, int value) +{ + return _write_aux_dac(to_slot(txrx, which_side), which_dac, value); +} + +bool +usrp_basic::common_read_aux_adc(txrx_t txrx, int which_side, int which_adc, int *value) +{ + return _read_aux_adc(to_slot(txrx, which_side), which_adc, value); +} + +int +usrp_basic::common_read_aux_adc(txrx_t txrx, int which_side, int which_adc) +{ + return _read_aux_adc(to_slot(txrx, which_side), which_adc); +} + + +//////////////////////////////////////////////////////////////// +// +// usrp_basic_rx +// +//////////////////////////////////////////////////////////////// + +static unsigned char rx_init_regs[] = { + REG_RX_PWR_DN, 0, + REG_RX_A, 0, // minimum gain = 0x00 (max gain = 0x14) + REG_RX_B, 0, // minimum gain = 0x00 (max gain = 0x14) + REG_RX_MISC, (RX_MISC_HS_DUTY_CYCLE | RX_MISC_CLK_DUTY), + REG_RX_IF, (RX_IF_USE_CLKOUT1 + | RX_IF_2S_COMP), + REG_RX_DIGITAL, (RX_DIGITAL_2_CHAN) +}; + + +usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename + ) + : usrp_basic (which_board, open_rx_interface, fpga_filename, firmware_filename), + d_devhandle (0), d_ephandle (0), + d_bytes_seen (0), d_first_read (true), + d_rx_enable (false) +{ + // initialize rx specific registers + + if (!usrp_9862_write_many_all (d_udh, rx_init_regs, sizeof (rx_init_regs))){ + fprintf (stderr, "usrp_basic_rx: failed to init AD9862 RX regs\n"); + throw std::runtime_error ("usrp_basic_rx/init_9862"); + } + + if (0){ + // FIXME power down 2nd codec rx path + usrp_9862_write (d_udh, 1, REG_RX_PWR_DN, 0x1); // power down everything + } + + // Reset the rx path and leave it disabled. + set_rx_enable (false); + usrp_set_fpga_rx_reset (d_udh, true); + usrp_set_fpga_rx_reset (d_udh, false); + + set_fpga_rx_sample_rate_divisor (2); // usually correct + + set_dc_offset_cl_enable(0xf, 0xf); // enable DC offset removal control loops + + probe_rx_slots (false); + + //d_db[0] = instantiate_dbs(d_dbid[0], this, 0); + //d_db[1] = instantiate_dbs(d_dbid[1], this, 1); + + // check fusb buffering parameters + + if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); + + if (fusb_nblocks < 0) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); + + if (fusb_block_size == 0) + fusb_block_size = fusb_sysconfig::default_block_size(); + + if (fusb_nblocks == 0) + fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); + + d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); + d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true, + fusb_block_size, fusb_nblocks); + + write_atr_mask(0, 0); // zero Rx A Auto Transmit/Receive regs + write_atr_txval(0, 0); + write_atr_rxval(0, 0); + write_atr_mask(1, 0); // zero Rx B Auto Transmit/Receive regs + write_atr_txval(1, 0); + write_atr_rxval(1, 0); +} + +static unsigned char rx_fini_regs[] = { + REG_RX_PWR_DN, 0x1 // power down everything +}; + +usrp_basic_rx::~usrp_basic_rx () +{ + if (!set_rx_enable (false)){ + fprintf (stderr, "usrp_basic_rx: set_fpga_rx_enable failed\n"); + } + + d_ephandle->stop (); + delete d_ephandle; + delete d_devhandle; + + if (!usrp_9862_write_many_all (d_udh, rx_fini_regs, sizeof (rx_fini_regs))){ + fprintf (stderr, "usrp_basic_rx: failed to fini AD9862 RX regs\n"); + } + + shutdown_daughterboards(); +} + + +bool +usrp_basic_rx::start () +{ + if (!usrp_basic::start ()) // invoke parent's method + return false; + + // fire off reads before asserting rx_enable + + if (!d_ephandle->start ()){ + fprintf (stderr, "usrp_basic_rx: failed to start end point streaming"); + return false; + } + + if (!set_rx_enable (true)){ + fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); + return false; + } + + return true; +} + +bool +usrp_basic_rx::stop () +{ + bool ok = usrp_basic::stop(); + + if (!set_rx_enable(false)){ + fprintf (stderr, "usrp_basic_rx: set_rx_enable(false) failed\n"); + ok = false; + } + + if (!d_ephandle->stop()){ + fprintf (stderr, "usrp_basic_rx: failed to stop end point streaming"); + ok = false; + } + + return ok; +} + +usrp_basic_rx * +usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) +{ + usrp_basic_rx *u = 0; + + try { + u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_basic_rx::set_fpga_rx_sample_rate_divisor (unsigned int div) +{ + return _write_fpga_reg (FR_RX_SAMPLE_RATE_DIV, div - 1); +} + + +/* + * \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 +usrp_basic_rx::read (void *buf, int len, bool *overrun) +{ + int r; + + if (overrun) + *overrun = false; + + if (len < 0 || (len % 512) != 0){ + fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len); + return -1; + } + + r = d_ephandle->read (buf, len); + if (r > 0) + d_bytes_seen += r; + + /* + * In many cases, the FPGA reports an rx overrun right after we + * enable the Rx path. If this is our first read, check for the + * overrun to clear the condition, then ignore the result. + */ + if (0 && d_first_read){ // FIXME + d_first_read = false; + bool bogus_overrun; + usrp_check_rx_overrun (d_udh, &bogus_overrun); + } + + if (overrun != 0 && d_bytes_seen >= d_bytes_per_poll){ + d_bytes_seen = 0; + if (!usrp_check_rx_overrun (d_udh, overrun)){ + fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n"); + } + } + + return r; +} + +bool +usrp_basic_rx::set_rx_enable (bool on) +{ + d_rx_enable = on; + return usrp_set_fpga_rx_enable (d_udh, on); +} + +// conditional disable, return prev state +bool +usrp_basic_rx::disable_rx () +{ + bool enabled = rx_enable (); + if (enabled) + set_rx_enable (false); + return enabled; +} + +// conditional set +void +usrp_basic_rx::restore_rx (bool on) +{ + if (on != rx_enable ()) + set_rx_enable (on); +} + +void +usrp_basic_rx::probe_rx_slots (bool verbose) +{ + struct usrp_dboard_eeprom eeprom; + static int slot_id_map[2] = { SLOT_RX_A, SLOT_RX_B }; + static const char *slot_name[2] = { "RX d'board A", "RX d'board B" }; + + for (int i = 0; i < 2; i++){ + int slot_id = slot_id_map [i]; + const char *msg = 0; + usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); + + switch (s){ + case UDBE_OK: + d_dbid[i] = eeprom.id; + msg = usrp_dbid_to_string (eeprom.id).c_str (); + set_adc_offset (2*i+0, eeprom.offset[0]); + set_adc_offset (2*i+1, eeprom.offset[1]); + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_NO_EEPROM: + d_dbid[i] = -1; + msg = ""; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_INVALID_EEPROM: + d_dbid[i] = -2; + msg = "Invalid EEPROM contents"; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_BAD_SLOT: + default: + assert (0); + } + + if (verbose){ + fflush (stdout); + fprintf (stderr, "%s: %s\n", slot_name[i], msg); + } + } +} + +bool +usrp_basic_rx::set_pga (int which_amp, double gain) +{ + return common_set_pga(C_RX, which_amp, gain); +} + +double +usrp_basic_rx::pga(int which_amp) const +{ + return common_pga(C_RX, which_amp); +} + +double +usrp_basic_rx::pga_min() const +{ + return common_pga_min(C_RX); +} + +double +usrp_basic_rx::pga_max() const +{ + return common_pga_max(C_RX); +} + +double +usrp_basic_rx::pga_db_per_step() const +{ + return common_pga_db_per_step(C_RX); +} + +bool +usrp_basic_rx::_write_oe (int which_side, int value, int mask) +{ + return _common_write_oe(C_RX, which_side, value, mask); +} + +bool +usrp_basic_rx::write_io (int which_side, int value, int mask) +{ + return common_write_io(C_RX, which_side, value, mask); +} + +bool +usrp_basic_rx::read_io (int which_side, int *value) +{ + return common_read_io(C_RX, which_side, value); +} + +int +usrp_basic_rx::read_io (int which_side) +{ + return common_read_io(C_RX, which_side); +} + +bool +usrp_basic_rx::write_refclk(int which_side, int value) +{ + return common_write_refclk(C_RX, which_side, value); +} + +bool +usrp_basic_rx::write_atr_mask(int which_side, int value) +{ + return common_write_atr_mask(C_RX, which_side, value); +} + +bool +usrp_basic_rx::write_atr_txval(int which_side, int value) +{ + return common_write_atr_txval(C_RX, which_side, value); +} + +bool +usrp_basic_rx::write_atr_rxval(int which_side, int value) +{ + return common_write_atr_rxval(C_RX, which_side, value); +} + +bool +usrp_basic_rx::write_aux_dac (int which_side, int which_dac, int value) +{ + return common_write_aux_dac(C_RX, which_side, which_dac, value); +} + +bool +usrp_basic_rx::read_aux_adc (int which_side, int which_adc, int *value) +{ + return common_read_aux_adc(C_RX, which_side, which_adc, value); +} + +int +usrp_basic_rx::read_aux_adc (int which_side, int which_adc) +{ + return common_read_aux_adc(C_RX, which_side, which_adc); +} + +int +usrp_basic_rx::block_size () const { return d_ephandle->block_size(); } + +//////////////////////////////////////////////////////////////// +// +// usrp_basic_tx +// +//////////////////////////////////////////////////////////////// + + +// +// DAC input rate 64 MHz interleaved for a total input rate of 128 MHz +// DAC input is latched on rising edge of CLKOUT2 +// NCO is disabled +// interpolate 2x +// coarse modulator disabled +// + +static unsigned char tx_init_regs[] = { + REG_TX_PWR_DN, 0, + REG_TX_A_OFFSET_LO, 0, + REG_TX_A_OFFSET_HI, 0, + REG_TX_B_OFFSET_LO, 0, + REG_TX_B_OFFSET_HI, 0, + REG_TX_A_GAIN, (TX_X_GAIN_COARSE_FULL | 0), + REG_TX_B_GAIN, (TX_X_GAIN_COARSE_FULL | 0), + REG_TX_PGA, 0xff, // maximum gain (0 dB) + REG_TX_MISC, 0, + REG_TX_IF, (TX_IF_USE_CLKOUT1 + | TX_IF_I_FIRST + | TX_IF_INV_TX_SYNC + | TX_IF_2S_COMP + | TX_IF_INTERLEAVED), + REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS + | TX_DIGITAL_INTERPOLATE_4X), + REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO + | TX_MODULATOR_COARSE_MODULATION_NONE), + REG_TX_NCO_FTW_7_0, 0, + REG_TX_NCO_FTW_15_8, 0, + REG_TX_NCO_FTW_23_16, 0 +}; + +usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) + : usrp_basic (which_board, open_tx_interface, fpga_filename, firmware_filename), + d_devhandle (0), d_ephandle (0), + d_bytes_seen (0), d_first_write (true), + d_tx_enable (false) +{ + if (!usrp_9862_write_many_all (d_udh, tx_init_regs, sizeof (tx_init_regs))){ + fprintf (stderr, "usrp_basic_tx: failed to init AD9862 TX regs\n"); + throw std::runtime_error ("usrp_basic_tx/init_9862"); + } + + if (0){ + // FIXME power down 2nd codec tx path + usrp_9862_write (d_udh, 1, REG_TX_PWR_DN, + (TX_PWR_DN_TX_DIGITAL + | TX_PWR_DN_TX_ANALOG_BOTH)); + } + + // Reset the tx path and leave it disabled. + set_tx_enable (false); + usrp_set_fpga_tx_reset (d_udh, true); + usrp_set_fpga_tx_reset (d_udh, false); + + set_fpga_tx_sample_rate_divisor (4); // we're using interp x4 + + probe_tx_slots (false); + + //d_db[0] = instantiate_dbs(d_dbid[0], this, 0); + //d_db[1] = instantiate_dbs(d_dbid[1], this, 1); + + // check fusb buffering parameters + + if (fusb_block_size < 0 || fusb_block_size > FUSB_BLOCK_SIZE) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_block_size"); + + if (fusb_nblocks < 0) + throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); + + if (fusb_block_size == 0) + fusb_block_size = FUSB_BLOCK_SIZE; + + if (fusb_nblocks == 0) + fusb_nblocks = std::max (1, FUSB_BUFFER_SIZE / fusb_block_size); + + d_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx); + d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false, + fusb_block_size, fusb_nblocks); + + write_atr_mask(0, 0); // zero Tx A Auto Transmit/Receive regs + write_atr_txval(0, 0); + write_atr_rxval(0, 0); + write_atr_mask(1, 0); // zero Tx B Auto Transmit/Receive regs + write_atr_txval(1, 0); + write_atr_rxval(1, 0); +} + + +static unsigned char tx_fini_regs[] = { + REG_TX_PWR_DN, (TX_PWR_DN_TX_DIGITAL + | TX_PWR_DN_TX_ANALOG_BOTH), + REG_TX_MODULATOR, (TX_MODULATOR_DISABLE_NCO + | TX_MODULATOR_COARSE_MODULATION_NONE) +}; + +usrp_basic_tx::~usrp_basic_tx () +{ + d_ephandle->stop (); + delete d_ephandle; + delete d_devhandle; + + if (!usrp_9862_write_many_all (d_udh, tx_fini_regs, sizeof (tx_fini_regs))){ + fprintf (stderr, "usrp_basic_tx: failed to fini AD9862 TX regs\n"); + } + + shutdown_daughterboards(); +} + +bool +usrp_basic_tx::start () +{ + if (!usrp_basic::start ()) + return false; + + if (!set_tx_enable (true)){ + fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); + return false; + } + + if (!d_ephandle->start ()){ + fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); + return false; + } + + return true; +} + +bool +usrp_basic_tx::stop () +{ + bool ok = usrp_basic::stop (); + + if (!d_ephandle->stop ()){ + fprintf (stderr, "usrp_basic_tx: failed to stop end point streaming"); + ok = false; + } + + if (!set_tx_enable (false)){ + fprintf (stderr, "usrp_basic_tx: set_tx_enable(false) failed\n"); + ok = false; + } + + return ok; +} + +usrp_basic_tx * +usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks, + const std::string fpga_filename, + const std::string firmware_filename) +{ + usrp_basic_tx *u = 0; + + try { + u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, + fpga_filename, firmware_filename); + return u; + } + catch (...){ + delete u; + return 0; + } + + return u; +} + +bool +usrp_basic_tx::set_fpga_tx_sample_rate_divisor (unsigned int div) +{ + return _write_fpga_reg (FR_TX_SAMPLE_RATE_DIV, div - 1); +} + +/*! + * \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 +usrp_basic_tx::write (const void *buf, int len, bool *underrun) +{ + int r; + + if (underrun) + *underrun = false; + + if (len < 0 || (len % 512) != 0){ + fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len); + return -1; + } + + r = d_ephandle->write (buf, len); + if (r > 0) + d_bytes_seen += r; + + /* + * In many cases, the FPGA reports an tx underrun right after we + * enable the Tx path. If this is our first write, check for the + * underrun to clear the condition, then ignore the result. + */ + if (d_first_write && d_bytes_seen >= 4 * FUSB_BLOCK_SIZE){ + d_first_write = false; + bool bogus_underrun; + usrp_check_tx_underrun (d_udh, &bogus_underrun); + } + + if (underrun != 0 && d_bytes_seen >= d_bytes_per_poll){ + d_bytes_seen = 0; + if (!usrp_check_tx_underrun (d_udh, underrun)){ + fprintf (stderr, "usrp_basic_tx: usrp_check_tx_underrun failed\n"); + } + } + + return r; +} + +void +usrp_basic_tx::wait_for_completion () +{ + d_ephandle->wait_for_completion (); +} + +bool +usrp_basic_tx::set_tx_enable (bool on) +{ + d_tx_enable = on; + // fprintf (stderr, "set_tx_enable %d\n", on); + return usrp_set_fpga_tx_enable (d_udh, on); +} + +// conditional disable, return prev state +bool +usrp_basic_tx::disable_tx () +{ + bool enabled = tx_enable (); + if (enabled) + set_tx_enable (false); + return enabled; +} + +// conditional set +void +usrp_basic_tx::restore_tx (bool on) +{ + if (on != tx_enable ()) + set_tx_enable (on); +} + +void +usrp_basic_tx::probe_tx_slots (bool verbose) +{ + struct usrp_dboard_eeprom eeprom; + static int slot_id_map[2] = { SLOT_TX_A, SLOT_TX_B }; + static const char *slot_name[2] = { "TX d'board A", "TX d'board B" }; + + for (int i = 0; i < 2; i++){ + int slot_id = slot_id_map [i]; + const char *msg = 0; + usrp_dbeeprom_status_t s = usrp_read_dboard_eeprom (d_udh, slot_id, &eeprom); + + switch (s){ + case UDBE_OK: + d_dbid[i] = eeprom.id; + msg = usrp_dbid_to_string (eeprom.id).c_str (); + // FIXME, figure out interpretation of dc offset for TX d'boards + // offset = (eeprom.offset[1] << 16) | (eeprom.offset[0] & 0xffff); + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_NO_EEPROM: + d_dbid[i] = -1; + msg = ""; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_INVALID_EEPROM: + d_dbid[i] = -2; + msg = "Invalid EEPROM contents"; + _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); + _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); + break; + + case UDBE_BAD_SLOT: + default: + assert (0); + } + + if (verbose){ + fflush (stdout); + fprintf (stderr, "%s: %s\n", slot_name[i], msg); + } + } +} + +bool +usrp_basic_tx::set_pga (int which_amp, double gain) +{ + return common_set_pga(C_TX, which_amp, gain); +} + +double +usrp_basic_tx::pga (int which_amp) const +{ + return common_pga(C_TX, which_amp); +} + +double +usrp_basic_tx::pga_min() const +{ + return common_pga_min(C_TX); +} + +double +usrp_basic_tx::pga_max() const +{ + return common_pga_max(C_TX); +} + +double +usrp_basic_tx::pga_db_per_step() const +{ + return common_pga_db_per_step(C_TX); +} + +bool +usrp_basic_tx::_write_oe (int which_side, int value, int mask) +{ + return _common_write_oe(C_TX, which_side, value, mask); +} + +bool +usrp_basic_tx::write_io (int which_side, int value, int mask) +{ + return common_write_io(C_TX, which_side, value, mask); +} + +bool +usrp_basic_tx::read_io (int which_side, int *value) +{ + return common_read_io(C_TX, which_side, value); +} + +int +usrp_basic_tx::read_io (int which_side) +{ + return common_read_io(C_TX, which_side); +} + +bool +usrp_basic_tx::write_refclk(int which_side, int value) +{ + return common_write_refclk(C_TX, which_side, value); +} + +bool +usrp_basic_tx::write_atr_mask(int which_side, int value) +{ + return common_write_atr_mask(C_TX, which_side, value); +} + +bool +usrp_basic_tx::write_atr_txval(int which_side, int value) +{ + return common_write_atr_txval(C_TX, which_side, value); +} + +bool +usrp_basic_tx::write_atr_rxval(int which_side, int value) +{ + return common_write_atr_rxval(C_TX, which_side, value); +} + +bool +usrp_basic_tx::write_aux_dac (int which_side, int which_dac, int value) +{ + return common_write_aux_dac(C_TX, which_side, which_dac, value); +} + +bool +usrp_basic_tx::read_aux_adc (int which_side, int which_adc, int *value) +{ + return common_read_aux_adc(C_TX, which_side, which_adc, value); +} + +int +usrp_basic_tx::read_aux_adc (int which_side, int which_adc) +{ + return common_read_aux_adc(C_TX, which_side, which_adc); +} + +int +usrp_basic_tx::block_size () const { return d_ephandle->block_size(); } + diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc new file mode 100644 index 000000000..296890b6c --- /dev/null +++ b/usrp/host/lib/usrp_basic_libusb.cc @@ -0,0 +1,146 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "usrp/usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include "fusb.h" +#include "db_boards.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// These set the buffer size used for each end point using the fast +// usb interface. The kernel ends up locking down this much memory. + +static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); +static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; + + +static const double POLLING_INTERVAL = 0.1; // seconds + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// These settings give us: +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + + +usrp_basic::usrp_basic (int which_board, + struct usb_dev_handle * + open_interface (struct usb_device *dev), + const std::string fpga_filename, + const std::string firmware_filename) + : d_udh (0), + d_usb_data_rate (16000000), // SWAG, see below + d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), + d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) +{ + /* + * SWAG: Scientific Wild Ass Guess. + * + * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the + * actual rate. This doesn't change our throughput, that's determined by the signal + * processing code in the FPGA (which we know nothing about), and the system limits + * determined by libusb, fusb_*, and the underlying drivers. + */ + memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); + + usrp_one_time_init (); + + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) + throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); + + struct usb_device *dev = usrp_find_device (which_board); + if (dev == 0){ + fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); + throw std::runtime_error ("usrp_basic/usrp_find_device"); + } + + if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ + fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); + throw std::runtime_error ("usrp_basic/bad_rev"); + } + + if ((d_udh = open_interface (dev)) == 0) + throw std::runtime_error ("usrp_basic/open_interface"); + + // initialize registers that are common to rx and tx + + if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ + fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); + throw std::runtime_error ("usrp_basic/init_9862"); + } + + _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode + _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs +} + +usrp_basic::~usrp_basic () +{ + // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} + + d_db.resize(0); // forget db shared ptrs + + if (d_udh) + usb_close (d_udh); +} + diff --git a/usrp/host/lib/usrp_prims.cc b/usrp/host/lib/usrp_prims.cc deleted file mode 100644 index d651a4529..000000000 --- a/usrp/host/lib/usrp_prims.cc +++ /dev/null @@ -1,1367 +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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "usrp/usrp_prims.h" -#include "usrp_commands.h" -#include "usrp_ids.h" -#include "usrp_i2c_addr.h" -#include "fpga_regs_common.h" -#include "fpga_regs_standard.h" -#include -#include -#include -#include -#include -#include -#include -#include // FIXME should check with autoconf (nanosleep) -#include -#include -#include - -extern "C" { -#include "md5.h" -}; - -#define VERBOSE 0 - -using namespace ad9862; - -static const int FIRMWARE_HASH_SLOT = 0; -static const int FPGA_HASH_SLOT = 1; - -static const int hash_slot_addr[2] = { - USRP_HASH_SLOT_0_ADDR, - USRP_HASH_SLOT_1_ADDR -}; - -static const char *default_firmware_filename = "std.ihx"; -static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; - -#include "std_paths.h" -#include - -static char * -find_file (const char *filename, int hw_rev) -{ - const char **sp = std_paths; - static char path[1000]; - char *s; - - s = getenv("USRP_PATH"); - if (s) { - snprintf (path, sizeof (path), "%s/rev%d/%s", s, hw_rev, filename); - if (access (path, R_OK) == 0) - return path; - } - - while (*sp){ - snprintf (path, sizeof (path), "%s/rev%d/%s", *sp, hw_rev, filename); - if (access (path, R_OK) == 0) - return path; - sp++; - } - return 0; -} - -static const char * -get_proto_filename(const std::string user_filename, const char *env_var, const char *def) -{ - if (user_filename.length() != 0) - return user_filename.c_str(); - - char *s = getenv(env_var); - if (s && *s) - return s; - - return def; -} - - -static void power_down_9862s (struct libusb_device_handle *udh); - -libusb_context * -usrp_one_time_init (bool new_context) -{ - - static bool first = true; - libusb_context *ctx = NULL; - int ret; - - // On first call create default context in addition to any new requested - // context. The default context is probably useless in this form, but keep - // it for now due to compatibility reasons. - - if (first) { - first = false; - if ((ret = libusb_init (NULL)) < 0) - fprintf (stderr, "usrp: libusb_init failed %i\n", ret); - } - - if (new_context) { - if ((ret = libusb_init (&ctx)) < 0) - fprintf (stderr, "usrp: libusb_init failed %i\n", ret); - } - - return ctx; -} - -void -usrp_rescan () -{ - // deprecated? -} - -// ---------------------------------------------------------------- - -/* - * q must be a real USRP, not an FX2. Return its hardware rev number. - */ -int -usrp_hw_rev (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return desc.bcdDevice & 0x00FF; -} - -/* - * q must be a real USRP, not an FX2. Return true if it's configured. - */ -static bool -_usrp_configured_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.bcdDevice & 0xFF00) != 0; -} - -bool -usrp_usrp_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.idVendor == USB_VID_FSF - && desc.idProduct == USB_PID_FSF_USRP); -} - -bool -usrp_fx2_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.idVendor == USB_VID_CYPRESS - && desc.idProduct == USB_PID_CYPRESS_FX2); -} - -bool -usrp_usrp0_p (struct libusb_device *q) -{ - return usrp_usrp_p (q) && usrp_hw_rev (q) == 0; -} - -bool -usrp_usrp1_p (struct libusb_device *q) -{ - return usrp_usrp_p (q) && usrp_hw_rev (q) == 1; -} - -bool -usrp_usrp2_p (struct libusb_device *q) -{ - return usrp_usrp_p (q) && usrp_hw_rev (q) == 2; -} - - -bool -usrp_unconfigured_usrp_p (struct libusb_device *q) -{ - return usrp_usrp_p (q) && !_usrp_configured_p (q); -} - -bool -usrp_configured_usrp_p (struct libusb_device *q) -{ - return usrp_usrp_p (q) && _usrp_configured_p (q); -} - -// ---------------------------------------------------------------- - -struct libusb_device * -usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) -{ - libusb_device **list; - - struct libusb_device *q; - int n_found = 0; - -//usrp_one_time_init (false); - assert (ctx != NULL); - - size_t cnt = libusb_get_device_list(ctx, &list); - size_t i = 0; - - if (cnt < 0) - fprintf(stderr, "usrp: libusb_get_device_list failed %d\n", cnt); - - for (i = 0; i < cnt; i++) { - q = list[i]; - if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) { - if (n_found == nth) // return this one - return q; - n_found++; // keep looking - } - } - -/* - * The list needs to be freed. Right just release it if nothing is found. - */ - - libusb_free_device_list(list, 1); - - return 0; // not found -} - -static struct libusb_device_handle * -usrp_open_interface (struct libusb_device *dev, int interface, int altinterface) -{ - struct libusb_device_handle *udh; - int ret; - - if (libusb_open (dev, &udh) < 0) - return 0; - - if (dev != libusb_get_device (udh)){ - fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); - abort (); - } - - if ((ret = libusb_claim_interface (udh, interface)) < 0) { - fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); - fprintf (stderr, "%d\n", ret); - libusb_close (udh); - return 0; - } - - if ((ret = libusb_set_interface_alt_setting (udh, interface, - altinterface)) < 0) { - fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); - fprintf (stderr, "%d\n", ret); - libusb_release_interface (udh, interface); - libusb_close (udh); - return 0; - } - - return udh; -} - -struct libusb_device_handle * -usrp_open_cmd_interface (struct libusb_device *dev) -{ - return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE); -} - -struct libusb_device_handle * -usrp_open_rx_interface (struct libusb_device *dev) -{ - return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE); -} - -struct libusb_device_handle * -usrp_open_tx_interface (struct libusb_device *dev) -{ - return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE); -} - -bool -usrp_close_interface (struct libusb_device_handle *udh) -{ - // returns void - libusb_close(udh); - return 0; -} - -// ---------------------------------------------------------------- -// write internal ram using Cypress vendor extension - -static bool -write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf, - int start_addr, size_t len) -{ - int addr; - int n; - int a; - int quanta = MAX_EP0_PKTSIZE; - - for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ - n = len + start_addr - addr; - if (n > quanta) - n = quanta; - - a = libusb_control_transfer (udh, 0x40, 0xA0, - addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); - - if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %u\n", a); - return false; - } - } - return true; -} - -// ---------------------------------------------------------------- -// whack the CPUCS register using the upload RAM vendor extension - -static bool -reset_cpu (struct libusb_device_handle *udh, bool reset_p) -{ - unsigned char v; - - if (reset_p) - v = 1; // hold processor in reset - else - v = 0; // release reset - - return write_internal_ram (udh, &v, 0xE600, 1); -} - -// ---------------------------------------------------------------- -// Load intel format file into cypress FX2 (8051) - -static bool -_usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, - unsigned char hash[USRP_HASH_SIZE]) -{ - FILE *f = fopen (filename, "ra"); - if (f == 0){ - perror (filename); - return false; - } - - if (!reset_cpu (udh, true)) // hold CPU in reset while loading firmware - goto fail; - - - char s[1024]; - int length; - int addr; - int type; - unsigned char data[256]; - unsigned char checksum, a; - unsigned int b; - int i; - - while (!feof(f)){ - fgets(s, sizeof (s), f); /* we should not use more than 263 bytes normally */ - if(s[0]!=':'){ - fprintf(stderr,"%s: invalid line: \"%s\"\n", filename, s); - goto fail; - } - sscanf(s+1, "%02x", &length); - sscanf(s+3, "%04x", &addr); - sscanf(s+7, "%02x", &type); - - if(type==0){ - - a=length+(addr &0xff)+(addr>>8)+type; - for(i=0;i 0){ - if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n) - goto fail; - } - - if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0) - goto fail; - - fclose (fp); - - if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash)) - fprintf (stderr, "usrp: failed to write fpga hash slot\n"); - - // On the rev1 USRP, the {tx,rx}_{enable,reset} bits are - // controlled over the serial bus, and hence aren't observed until - // we've got a good fpga bitstream loaded. - - usrp_set_fpga_reset (udh, 0); // fpga out of master reset - - // now these commands will work - - ok &= usrp_set_fpga_tx_enable (udh, 0); - ok &= usrp_set_fpga_rx_enable (udh, 0); - - ok &= usrp_set_fpga_tx_reset (udh, 1); // reset tx and rx paths - ok &= usrp_set_fpga_rx_reset (udh, 1); - ok &= usrp_set_fpga_tx_reset (udh, 0); // reset tx and rx paths - ok &= usrp_set_fpga_rx_reset (udh, 0); - - if (!ok) - fprintf (stderr, "usrp: failed to reset tx and/or rx path\n"); - - // Manually reset all regs except master control to zero. - // FIXME may want to remove this when we rework FPGA reset strategy. - // In the mean while, this gets us reproducible behavior. - for (int i = 0; i < FR_USER_0; i++){ - if (i == FR_MASTER_CTRL) - continue; - usrp_write_fpga_reg(udh, i, 0); - } - - power_down_9862s (udh); // on the rev1, power these down! - usrp_set_led (udh, 1, 0); // led 1 off - - return true; - - fail: - power_down_9862s (udh); // on the rev1, power these down! - fclose (fp); - return false; -} - -// ---------------------------------------------------------------- - -bool -usrp_set_led (struct libusb_device_handle *udh, int which, bool on) -{ - int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); - - return r == 0; -} - -bool -usrp_set_hash (struct libusb_device_handle *udh, int which, - const unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware down load command to jam it in. - int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -bool -usrp_get_hash (struct libusb_device_handle *udh, int which, - unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware upload command to fetch it. - int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -static bool -usrp_set_switch (struct libusb_device_handle *udh, int cmd_byte, bool on) -{ - return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; -} - - -static bool -usrp1_fpga_write (struct libusb_device_handle *udh, - int regno, int value) -{ - // on the rev1 usrp, we use the generic spi_write interface - - unsigned char buf[4]; - - buf[0] = (value >> 24) & 0xff; // MSB first - buf[1] = (value >> 16) & 0xff; - buf[2] = (value >> 8) & 0xff; - buf[3] = (value >> 0) & 0xff; - - return usrp_spi_write (udh, 0x00 | (regno & 0x7f), - SPI_ENABLE_FPGA, - SPI_FMT_MSB | SPI_FMT_HDR_1, - buf, sizeof (buf)); -} - -static bool -usrp1_fpga_read (struct libusb_device_handle *udh, - int regno, int *value) -{ - *value = 0; - unsigned char buf[4]; - - bool ok = usrp_spi_read (udh, 0x80 | (regno & 0x7f), - SPI_ENABLE_FPGA, - SPI_FMT_MSB | SPI_FMT_HDR_1, - buf, sizeof (buf)); - - if (ok) - *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - - return ok; -} - - -bool -usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_write (udh, reg, value); - } -} - -bool -usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_read (udh, reg, value); - } -} - -bool -usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on) -{ - return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); -} - -bool -usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on) -{ - return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); -} - -bool -usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on) -{ - return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); -} - -bool -usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on) -{ - return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); -} - -bool -usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on) -{ - return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); -} - - -// ---------------------------------------------------------------- -// conditional load stuff - -static bool -compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) -{ - assert (USRP_HASH_SIZE == 16); - memset (hash, 0, USRP_HASH_SIZE); - - FILE *fp = fopen (filename, "rb"); - if (fp == 0){ - perror (filename); - return false; - } - int r = md5_stream (fp, hash); - fclose (fp); - - return r == 0; -} - -static usrp_load_status_t -usrp_conditionally_load_something (struct libusb_device_handle *udh, - const char *filename, - bool force, - int slot, - bool loader (struct libusb_device_handle *, - const char *, - unsigned char [USRP_HASH_SIZE])) -{ - unsigned char file_hash[USRP_HASH_SIZE]; - unsigned char usrp_hash[USRP_HASH_SIZE]; - - if (access (filename, R_OK) != 0){ - perror (filename); - return ULS_ERROR; - } - - if (!compute_hash (filename, file_hash)) - return ULS_ERROR; - - if (!force - && usrp_get_hash (udh, slot, usrp_hash) - && memcmp (file_hash, usrp_hash, USRP_HASH_SIZE) == 0) - return ULS_ALREADY_LOADED; - - bool r = loader (udh, filename, file_hash); - - if (!r) - return ULS_ERROR; - - return ULS_OK; -} - -usrp_load_status_t -usrp_load_firmware (struct libusb_device_handle *udh, - const char *filename, - bool force) -{ - return usrp_conditionally_load_something (udh, filename, force, - FIRMWARE_HASH_SLOT, - _usrp_load_firmware); -} - -usrp_load_status_t -usrp_load_fpga (struct libusb_device_handle *udh, - const char *filename, - bool force) -{ - return usrp_conditionally_load_something (udh, filename, force, - FPGA_HASH_SLOT, - _usrp_load_fpga); -} - -static libusb_device_handle * -open_nth_cmd_interface (int nth, libusb_context *ctx) -{ - - struct libusb_device *udev = usrp_find_device (nth, false, ctx); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return 0; - } - - struct libusb_device_handle *udh; - - udh = usrp_open_cmd_interface (udev); - if (udh == 0){ - // FIXME this could be because somebody else has it open. - // We should delay and retry... - fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); - return 0; - } - - return udh; - } - -static bool -our_nanosleep (const struct timespec *delay) -{ - struct timespec new_delay = *delay; - struct timespec remainder; - - while (1){ - int r = nanosleep (&new_delay, &remainder); - if (r == 0) - return true; - if (errno == EINTR) - new_delay = remainder; - else { - perror ("nanosleep"); - return false; - } - } -} - -static bool -mdelay (int millisecs) -{ - struct timespec ts; - ts.tv_sec = millisecs / 1000; - ts.tv_nsec = (millisecs - (1000 * ts.tv_sec)) * 1000000; - return our_nanosleep (&ts); -} - -usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx) -{ - struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); - if (udh == 0) - return ULS_ERROR; - - usrp_load_status_t s = usrp_load_firmware (udh, filename, force); - usrp_close_interface (udh); - - switch (s){ - - case ULS_ALREADY_LOADED: // nothing changed... - return ULS_ALREADY_LOADED; - break; - - case ULS_OK: - // we loaded firmware successfully. - - // It's highly likely that the board will renumerate (simulate a - // disconnect/reconnect sequence), invalidating our current - // handle. - - // FIXME. Turn this into a loop that rescans until we refind ourselves - - struct timespec t; // delay for 1 second - t.tv_sec = 2; - t.tv_nsec = 0; - our_nanosleep (&t); - - return ULS_OK; - - default: - case ULS_ERROR: // some kind of problem - return ULS_ERROR; - } -} - -static void -load_status_msg (usrp_load_status_t s, const char *type, const char *filename) -{ - char *e = getenv("USRP_VERBOSE"); - bool verbose = e != 0; - - switch (s){ - case ULS_ERROR: - fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename); - break; - - case ULS_ALREADY_LOADED: - if (verbose) - fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename); - break; - - case ULS_OK: - if (verbose) - fprintf (stderr, "usrp: %s %s loaded successfully.\n", type, filename); - break; - } -} - -bool -usrp_load_standard_bits (int nth, bool force, - const std::string fpga_filename, - const std::string firmware_filename, - libusb_context *ctx) -{ - usrp_load_status_t s; - const char *filename; - const char *proto_filename; - int hw_rev; - - assert (ctx != NULL); - - // first, figure out what hardware rev we're dealing with - { - struct libusb_device *udev = usrp_find_device (nth, false, ctx); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return false; - } - hw_rev = usrp_hw_rev (udev); - } - - // start by loading the firmware - - proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", - default_firmware_filename); - filename = find_file(proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find firmware: %s\n", proto_filename); - return false; - } - s = usrp_load_firmware_nth (nth, filename, force, ctx); - load_status_msg (s, "firmware", filename); - - if (s == ULS_ERROR) - return false; - - // if we actually loaded firmware, we must reload fpga ... - if (s == ULS_OK) - force = true; - - // now move on to the fpga configuration bitstream - - proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", - default_fpga_filename); - filename = find_file (proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); - return false; - } - struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); - if (udh == 0) - return false; - - s = usrp_load_fpga (udh, filename, force); - usrp_close_interface (udh); - load_status_msg (s, "fpga bitstream", filename); - - if (s == ULS_ERROR) - return false; - - return true; -} - -bool -_usrp_get_status (struct libusb_device_handle *udh, int which, bool *trouble) -{ - unsigned char status; - *trouble = true; - - if (write_cmd (udh, VRQ_GET_STATUS, 0, which, - &status, sizeof (status)) != sizeof (status)) - return false; - - *trouble = status; - return true; -} - -bool -usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p) -{ - return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p); -} - -bool -usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p) -{ - return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p); -} - - -bool -usrp_i2c_write (struct libusb_device_handle *udh, int i2c_addr, - const void *buf, int len) -{ - if (len < 1 || len > MAX_EP0_PKTSIZE) - return false; - - return write_cmd (udh, VRQ_I2C_WRITE, i2c_addr, 0, - (unsigned char *) buf, len) == len; -} - - -bool -usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, - void *buf, int len) -{ - if (len < 1 || len > MAX_EP0_PKTSIZE) - return false; - - return write_cmd (udh, VRQ_I2C_READ, i2c_addr, 0, - (unsigned char *) buf, len) == len; -} - -bool -usrp_spi_write (struct libusb_device_handle *udh, - int optional_header, int enables, int format, - const void *buf, int len) -{ - if (len < 0 || len > MAX_EP0_PKTSIZE) - return false; - - return write_cmd (udh, VRQ_SPI_WRITE, - optional_header, - ((enables & 0xff) << 8) | (format & 0xff), - (unsigned char *) buf, len) == len; -} - - -bool -usrp_spi_read (struct libusb_device_handle *udh, - int optional_header, int enables, int format, - void *buf, int len) -{ - if (len < 0 || len > MAX_EP0_PKTSIZE) - return false; - - return write_cmd (udh, VRQ_SPI_READ, - optional_header, - ((enables & 0xff) << 8) | (format & 0xff), - (unsigned char *) buf, len) == len; -} - -bool -usrp_9862_write (struct libusb_device_handle *udh, int which_codec, - int regno, int value) -{ - if (0) - fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n", - which_codec, regno, value, value); - - unsigned char buf[1]; - - buf[0] = value; - - return usrp_spi_write (udh, 0x00 | (regno & 0x3f), - which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, - SPI_FMT_MSB | SPI_FMT_HDR_1, - buf, 1); -} - -bool -usrp_9862_read (struct libusb_device_handle *udh, int which_codec, - int regno, unsigned char *value) -{ - return usrp_spi_read (udh, 0x80 | (regno & 0x3f), - which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, - SPI_FMT_MSB | SPI_FMT_HDR_1, - value, 1); -} - -bool -usrp_9862_write_many (struct libusb_device_handle *udh, - int which_codec, - const unsigned char *buf, - int len) -{ - if (len & 0x1) - return false; // must be even - - bool result = true; - - while (len > 0){ - result &= usrp_9862_write (udh, which_codec, buf[0], buf[1]); - len -= 2; - buf += 2; - } - - return result; -} - - -bool -usrp_9862_write_many_all (struct libusb_device_handle *udh, - const unsigned char *buf, int len) -{ - // FIXME handle 2/2 and 4/4 versions - - bool result; - result = usrp_9862_write_many (udh, 0, buf, len); - result &= usrp_9862_write_many (udh, 1, buf, len); - return result; -} - -static void -power_down_9862s (struct libusb_device_handle *udh) -{ - static const unsigned char regs[] = { - REG_RX_PWR_DN, 0x01, // everything - REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both - REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled - }; - - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: - break; - - default: - usrp_9862_write_many_all (udh, regs, sizeof (regs)); - break; - } -} - - - -static const int EEPROM_PAGESIZE = 16; - -bool -usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, - int eeprom_offset, const void *buf, int len) -{ - unsigned char cmd[2]; - const unsigned char *p = (unsigned char *) buf; - - // The simplest thing that could possibly work: - // all writes are single byte writes. - // - // We could speed this up using the page write feature, - // but we write so infrequently, why bother... - - while (len-- > 0){ - cmd[0] = eeprom_offset++; - cmd[1] = *p++; - bool r = usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd)); - mdelay (10); // delay 10ms worst case write time - if (!r) - return false; - } - - return true; -} - -bool -usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, - int eeprom_offset, void *buf, int len) -{ - unsigned char *p = (unsigned char *) buf; - - // We setup a random read by first doing a "zero byte write". - // Writes carry an address. Reads use an implicit address. - - unsigned char cmd[1]; - cmd[0] = eeprom_offset; - if (!usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd))) - return false; - - while (len > 0){ - int n = std::min (len, MAX_EP0_PKTSIZE); - if (!usrp_i2c_read (udh, i2c_addr, p, n)) - return false; - len -= n; - p += n; - } - return true; -} - -// ---------------------------------------------------------------- - -static bool -slot_to_codec (int slot, int *which_codec) -{ - *which_codec = 0; - - switch (slot){ - case SLOT_TX_A: - case SLOT_RX_A: - *which_codec = 0; - break; - - case SLOT_TX_B: - case SLOT_RX_B: - *which_codec = 1; - break; - - default: - fprintf (stderr, "usrp_prims:slot_to_codec: invalid slot = %d\n", slot); - return false; - } - return true; -} - -static bool -tx_slot_p (int slot) -{ - switch (slot){ - case SLOT_TX_A: - case SLOT_TX_B: - return true; - - default: - return false; - } -} - -bool -usrp_write_aux_dac (struct libusb_device_handle *udh, int slot, - int which_dac, int value) -{ - int which_codec; - - if (!slot_to_codec (slot, &which_codec)) - return false; - - if (!(0 <= which_dac && which_dac < 4)){ - fprintf (stderr, "usrp_write_aux_dac: invalid dac = %d\n", which_dac); - return false; - } - - value &= 0x0fff; // mask to 12-bits - - if (which_dac == 3){ - // dac 3 is really 12-bits. Use value as is. - bool r = true; - r &= usrp_9862_write (udh, which_codec, 43, (value >> 4)); // most sig - r &= usrp_9862_write (udh, which_codec, 42, (value & 0xf) << 4); // least sig - return r; - } - else { - // dac 0, 1, and 2 are really 8 bits. - value = value >> 4; // shift value appropriately - return usrp_9862_write (udh, which_codec, 36 + which_dac, value); - } -} - - -bool -usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, - int which_adc, int *value) -{ - *value = 0; - int which_codec; - - if (!slot_to_codec (slot, &which_codec)) - return false; - - if (!(0 <= which_codec && which_codec < 2)){ - fprintf (stderr, "usrp_read_aux_adc: invalid adc = %d\n", which_adc); - return false; - } - - unsigned char aux_adc_control = - AUX_ADC_CTRL_REFSEL_A // on chip reference - | AUX_ADC_CTRL_REFSEL_B; // on chip reference - - int rd_reg = 26; // base address of two regs to read for result - - // program the ADC mux bits - if (tx_slot_p (slot)) - aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2; - else { - rd_reg += 2; - aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1; - } - - // I'm not sure if we can set the mux and issue a start conversion - // in the same cycle, so let's do them one at a time. - - usrp_9862_write (udh, which_codec, 34, aux_adc_control); - - if (which_adc == 0) - aux_adc_control |= AUX_ADC_CTRL_START_A; - else { - rd_reg += 4; - aux_adc_control |= AUX_ADC_CTRL_START_B; - } - - // start the conversion - usrp_9862_write (udh, which_codec, 34, aux_adc_control); - - // read the 10-bit result back - unsigned char v_lo = 0; - unsigned char v_hi = 0; - bool r = usrp_9862_read (udh, which_codec, rd_reg, &v_lo); - r &= usrp_9862_read (udh, which_codec, rd_reg + 1, &v_hi); - - if (r) - *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit - - return r; -} - -// ---------------------------------------------------------------- - -static int slot_to_i2c_addr (int slot) -{ - switch (slot){ - case SLOT_TX_A: return I2C_ADDR_TX_A; - case SLOT_RX_A: return I2C_ADDR_RX_A; - case SLOT_TX_B: return I2C_ADDR_TX_B; - case SLOT_RX_B: return I2C_ADDR_RX_B; - default: return -1; - } -} - -static void -set_chksum (unsigned char *buf) -{ - int sum = 0; - unsigned int i; - for (i = 0; i < DB_EEPROM_CLEN - 1; i++) - sum += buf[i]; - buf[i] = -sum; -} - -static usrp_dbeeprom_status_t -read_dboard_eeprom (struct libusb_device_handle *udh, - int slot_id, unsigned char *buf) -{ - int i2c_addr = slot_to_i2c_addr (slot_id); - if (i2c_addr == -1) - return UDBE_BAD_SLOT; - - if (!usrp_eeprom_read (udh, i2c_addr, 0, buf, DB_EEPROM_CLEN)) - return UDBE_NO_EEPROM; - - if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE) - return UDBE_INVALID_EEPROM; - - int sum = 0; - for (unsigned int i = 0; i < DB_EEPROM_CLEN; i++) - sum += buf[i]; - - if ((sum & 0xff) != 0) - return UDBE_INVALID_EEPROM; - - return UDBE_OK; -} - -usrp_dbeeprom_status_t -usrp_read_dboard_eeprom (struct libusb_device_handle *udh, - int slot_id, usrp_dboard_eeprom *eeprom) -{ - unsigned char buf[DB_EEPROM_CLEN]; - - memset (eeprom, 0, sizeof (*eeprom)); - - usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); - if (s != UDBE_OK) - return s; - - eeprom->id = (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB]; - eeprom->oe = (buf[DB_EEPROM_OE_MSB] << 8) | buf[DB_EEPROM_OE_LSB]; - eeprom->offset[0] = (buf[DB_EEPROM_OFFSET_0_MSB] << 8) | buf[DB_EEPROM_OFFSET_0_LSB]; - eeprom->offset[1] = (buf[DB_EEPROM_OFFSET_1_MSB] << 8) | buf[DB_EEPROM_OFFSET_1_LSB]; - - return UDBE_OK; -} - -bool -usrp_write_dboard_offsets (struct libusb_device_handle *udh, int slot_id, - short offset0, short offset1) -{ - unsigned char buf[DB_EEPROM_CLEN]; - - usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); - if (s != UDBE_OK) - return false; - - buf[DB_EEPROM_OFFSET_0_LSB] = (offset0 >> 0) & 0xff; - buf[DB_EEPROM_OFFSET_0_MSB] = (offset0 >> 8) & 0xff; - buf[DB_EEPROM_OFFSET_1_LSB] = (offset1 >> 0) & 0xff; - buf[DB_EEPROM_OFFSET_1_MSB] = (offset1 >> 8) & 0xff; - set_chksum (buf); - - return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id), - 0, buf, sizeof (buf)); -} - -std::string -usrp_serial_number(struct libusb_device_handle *udh) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - unsigned char iserial = desc.iSerialNumber; - if (iserial == 0) - return ""; - - unsigned char buf[1024]; - if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0) - return ""; - - return (char*) buf; -} diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc new file mode 100644 index 000000000..4b695bec5 --- /dev/null +++ b/usrp/host/lib/usrp_prims_common.cc @@ -0,0 +1,965 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp/usrp_prims.h" +#include "usrp_commands.h" +#include "usrp_ids.h" +#include "usrp_i2c_addr.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include +#include +#include +#include // FIXME should check with autoconf (nanosleep) +#include +#include +#include + +#if 1 +#include +#else +#include +#endif + +extern "C" { +#include "md5.h" +}; + +#define VERBOSE 0 + +using namespace ad9862; + +static const int FIRMWARE_HASH_SLOT = 0; +static const int FPGA_HASH_SLOT = 1; + +static const int hash_slot_addr[2] = { + USRP_HASH_SLOT_0_ADDR, + USRP_HASH_SLOT_1_ADDR +}; + +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 + +char * +find_file (const char *filename, int hw_rev) +{ + const char **sp = std_paths; + static char path[1000]; + char *s; + + s = getenv("USRP_PATH"); + if (s) { + snprintf (path, sizeof (path), "%s/rev%d/%s", s, hw_rev, filename); + if (access (path, R_OK) == 0) + return path; + } + + while (*sp){ + snprintf (path, sizeof (path), "%s/rev%d/%s", *sp, hw_rev, filename); + if (access (path, R_OK) == 0) + return path; + sp++; + } + return 0; +} + +const char * +get_proto_filename(const std::string user_filename, const char *env_var, const char *def) +{ + if (user_filename.length() != 0) + return user_filename.c_str(); + + char *s = getenv(env_var); + if (s && *s) + return s; + + return def; +} + + +void power_down_9862s (libusb_device_handle *udh); + +// ---------------------------------------------------------------- + +bool +usrp_usrp0_p (libusb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 0; +} + +bool +usrp_usrp1_p (libusb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 1; +} + +bool +usrp_usrp2_p (libusb_device *q) +{ + return usrp_usrp_p (q) && usrp_hw_rev (q) == 2; +} + + +bool +usrp_unconfigured_usrp_p (libusb_device *q) +{ + return usrp_usrp_p (q) && !_usrp_configured_p (q); +} + +bool +usrp_configured_usrp_p (libusb_device *q) +{ + return usrp_usrp_p (q) && _usrp_configured_p (q); +} + +libusb_device_handle * +usrp_open_cmd_interface (libusb_device *dev) +{ + return usrp_open_interface (dev, USRP_CMD_INTERFACE, USRP_CMD_ALTINTERFACE); +} + +libusb_device_handle * +usrp_open_rx_interface (libusb_device *dev) +{ + return usrp_open_interface (dev, USRP_RX_INTERFACE, USRP_RX_ALTINTERFACE); +} + +libusb_device_handle * +usrp_open_tx_interface (libusb_device *dev) +{ + return usrp_open_interface (dev, USRP_TX_INTERFACE, USRP_TX_ALTINTERFACE); +} + + +// ---------------------------------------------------------------- +// whack the CPUCS register using the upload RAM vendor extension + +static bool +reset_cpu (libusb_device_handle *udh, bool reset_p) +{ + unsigned char v; + + if (reset_p) + v = 1; // hold processor in reset + else + v = 0; // release reset + + return write_internal_ram (udh, &v, 0xE600, 1); +} + +// ---------------------------------------------------------------- +// Load intel format file into cypress FX2 (8051) + +static bool +_usrp_load_firmware (libusb_device_handle *udh, const char *filename, + unsigned char hash[USRP_HASH_SIZE]) +{ + FILE *f = fopen (filename, "ra"); + if (f == 0){ + perror (filename); + return false; + } + + if (!reset_cpu (udh, true)) // hold CPU in reset while loading firmware + goto fail; + + + char s[1024]; + int length; + int addr; + int type; + unsigned char data[256]; + unsigned char checksum, a; + unsigned int b; + int i; + + while (!feof(f)){ + fgets(s, sizeof (s), f); /* we should not use more than 263 bytes normally */ + if(s[0]!=':'){ + fprintf(stderr,"%s: invalid line: \"%s\"\n", filename, s); + goto fail; + } + sscanf(s+1, "%02x", &length); + sscanf(s+3, "%04x", &addr); + sscanf(s+7, "%02x", &type); + + if(type==0){ + + a=length+(addr &0xff)+(addr>>8)+type; + for(i=0;i 0){ + if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n) + goto fail; + } + + if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0) + goto fail; + + fclose (fp); + + if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash)) + fprintf (stderr, "usrp: failed to write fpga hash slot\n"); + + // On the rev1 USRP, the {tx,rx}_{enable,reset} bits are + // controlled over the serial bus, and hence aren't observed until + // we've got a good fpga bitstream loaded. + + usrp_set_fpga_reset (udh, 0); // fpga out of master reset + + // now these commands will work + + ok &= usrp_set_fpga_tx_enable (udh, 0); + ok &= usrp_set_fpga_rx_enable (udh, 0); + + ok &= usrp_set_fpga_tx_reset (udh, 1); // reset tx and rx paths + ok &= usrp_set_fpga_rx_reset (udh, 1); + ok &= usrp_set_fpga_tx_reset (udh, 0); // reset tx and rx paths + ok &= usrp_set_fpga_rx_reset (udh, 0); + + if (!ok) + fprintf (stderr, "usrp: failed to reset tx and/or rx path\n"); + + // Manually reset all regs except master control to zero. + // FIXME may want to remove this when we rework FPGA reset strategy. + // In the mean while, this gets us reproducible behavior. + for (int i = 0; i < FR_USER_0; i++){ + if (i == FR_MASTER_CTRL) + continue; + usrp_write_fpga_reg(udh, i, 0); + } + + power_down_9862s (udh); // on the rev1, power these down! + usrp_set_led (udh, 1, 0); // led 1 off + + return true; + + fail: + power_down_9862s (udh); // on the rev1, power these down! + fclose (fp); + return false; +} + +// ---------------------------------------------------------------- + +bool +usrp_set_led (libusb_device_handle *udh, int which, bool on) +{ + int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); + + return r == 0; +} + + +bool +usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on) +{ + return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; +} + +bool +usrp1_fpga_write (libusb_device_handle *udh, + int regno, int value) +{ + // on the rev1 usrp, we use the generic spi_write interface + + unsigned char buf[4]; + + buf[0] = (value >> 24) & 0xff; // MSB first + buf[1] = (value >> 16) & 0xff; + buf[2] = (value >> 8) & 0xff; + buf[3] = (value >> 0) & 0xff; + + return usrp_spi_write (udh, 0x00 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, sizeof (buf)); +} + +bool +usrp1_fpga_read (libusb_device_handle *udh, + int regno, int *value) +{ + *value = 0; + unsigned char buf[4]; + + bool ok = usrp_spi_read (udh, 0x80 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, sizeof (buf)); + + if (ok) + *value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + return ok; +} + + +bool +usrp_set_fpga_reset (libusb_device_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); +} + +bool +usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); +} + +bool +usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); +} + +bool +usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); +} + +bool +usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on) +{ + return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); +} + + +// ---------------------------------------------------------------- +// conditional load stuff + +static bool +compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) +{ + assert (USRP_HASH_SIZE == 16); + memset (hash, 0, USRP_HASH_SIZE); + + FILE *fp = fopen (filename, "rb"); + if (fp == 0){ + perror (filename); + return false; + } + int r = md5_stream (fp, hash); + fclose (fp); + + return r == 0; +} + +static usrp_load_status_t +usrp_conditionally_load_something (libusb_device_handle *udh, + const char *filename, + bool force, + int slot, + bool loader (libusb_device_handle *, + const char *, + unsigned char [USRP_HASH_SIZE])) +{ + unsigned char file_hash[USRP_HASH_SIZE]; + unsigned char usrp_hash[USRP_HASH_SIZE]; + + if (access (filename, R_OK) != 0){ + perror (filename); + return ULS_ERROR; + } + + if (!compute_hash (filename, file_hash)) + return ULS_ERROR; + + if (!force + && usrp_get_hash (udh, slot, usrp_hash) + && memcmp (file_hash, usrp_hash, USRP_HASH_SIZE) == 0) + return ULS_ALREADY_LOADED; + + bool r = loader (udh, filename, file_hash); + + if (!r) + return ULS_ERROR; + + return ULS_OK; +} + +usrp_load_status_t +usrp_load_firmware (libusb_device_handle *udh, + const char *filename, + bool force) +{ + return usrp_conditionally_load_something (udh, filename, force, + FIRMWARE_HASH_SLOT, + _usrp_load_firmware); +} + +usrp_load_status_t +usrp_load_fpga (libusb_device_handle *udh, + const char *filename, + bool force) +{ + return usrp_conditionally_load_something (udh, filename, force, + FPGA_HASH_SLOT, + _usrp_load_fpga); +} + +bool +our_nanosleep (const struct timespec *delay) +{ + struct timespec new_delay = *delay; + struct timespec remainder; + + while (1){ + int r = nanosleep (&new_delay, &remainder); + if (r == 0) + return true; + if (errno == EINTR) + new_delay = remainder; + else { + perror ("nanosleep"); + return false; + } + } +} + +static bool +mdelay (int millisecs) +{ + struct timespec ts; + ts.tv_sec = millisecs / 1000; + ts.tv_nsec = (millisecs - (1000 * ts.tv_sec)) * 1000000; + return our_nanosleep (&ts); +} + +void +load_status_msg (usrp_load_status_t s, const char *type, const char *filename) +{ + char *e = getenv("USRP_VERBOSE"); + bool verbose = e != 0; + + switch (s){ + case ULS_ERROR: + fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename); + break; + + case ULS_ALREADY_LOADED: + if (verbose) + fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename); + break; + + case ULS_OK: + if (verbose) + fprintf (stderr, "usrp: %s %s loaded successfully.\n", type, filename); + break; + } +} + +bool +_usrp_get_status (libusb_device_handle *udh, int which, bool *trouble) +{ + unsigned char status; + *trouble = true; + + if (write_cmd (udh, VRQ_GET_STATUS, 0, which, + &status, sizeof (status)) != sizeof (status)) + return false; + + *trouble = status; + return true; +} + +bool +usrp_check_rx_overrun (libusb_device_handle *udh, bool *overrun_p) +{ + return _usrp_get_status (udh, GS_RX_OVERRUN, overrun_p); +} + +bool +usrp_check_tx_underrun (libusb_device_handle *udh, bool *underrun_p) +{ + return _usrp_get_status (udh, GS_TX_UNDERRUN, underrun_p); +} + + +bool +usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, + const void *buf, int len) +{ + if (len < 1 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_I2C_WRITE, i2c_addr, 0, + (unsigned char *) buf, len) == len; +} + + +bool +usrp_i2c_read (libusb_device_handle *udh, int i2c_addr, + void *buf, int len) +{ + if (len < 1 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_I2C_READ, i2c_addr, 0, + (unsigned char *) buf, len) == len; +} + +bool +usrp_spi_write (libusb_device_handle *udh, + int optional_header, int enables, int format, + const void *buf, int len) +{ + if (len < 0 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_SPI_WRITE, + optional_header, + ((enables & 0xff) << 8) | (format & 0xff), + (unsigned char *) buf, len) == len; +} + + +bool +usrp_spi_read (libusb_device_handle *udh, + int optional_header, int enables, int format, + void *buf, int len) +{ + if (len < 0 || len > MAX_EP0_PKTSIZE) + return false; + + return write_cmd (udh, VRQ_SPI_READ, + optional_header, + ((enables & 0xff) << 8) | (format & 0xff), + (unsigned char *) buf, len) == len; +} + +bool +usrp_9862_write (libusb_device_handle *udh, int which_codec, + int regno, int value) +{ + if (0) + fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n", + which_codec, regno, value, value); + + unsigned char buf[1]; + + buf[0] = value; + + return usrp_spi_write (udh, 0x00 | (regno & 0x3f), + which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + buf, 1); +} + +bool +usrp_9862_read (libusb_device_handle *udh, int which_codec, + int regno, unsigned char *value) +{ + return usrp_spi_read (udh, 0x80 | (regno & 0x3f), + which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + value, 1); +} + +bool +usrp_9862_write_many (libusb_device_handle *udh, + int which_codec, + const unsigned char *buf, + int len) +{ + if (len & 0x1) + return false; // must be even + + bool result = true; + + while (len > 0){ + result &= usrp_9862_write (udh, which_codec, buf[0], buf[1]); + len -= 2; + buf += 2; + } + + return result; +} + + +bool +usrp_9862_write_many_all (libusb_device_handle *udh, + const unsigned char *buf, int len) +{ + // FIXME handle 2/2 and 4/4 versions + + bool result; + result = usrp_9862_write_many (udh, 0, buf, len); + result &= usrp_9862_write_many (udh, 1, buf, len); + return result; +} + + +static const int EEPROM_PAGESIZE = 16; + +bool +usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, + int eeprom_offset, const void *buf, int len) +{ + unsigned char cmd[2]; + const unsigned char *p = (unsigned char *) buf; + + // The simplest thing that could possibly work: + // all writes are single byte writes. + // + // We could speed this up using the page write feature, + // but we write so infrequently, why bother... + + while (len-- > 0){ + cmd[0] = eeprom_offset++; + cmd[1] = *p++; + bool r = usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd)); + mdelay (10); // delay 10ms worst case write time + if (!r) + return false; + } + + return true; +} + +bool +usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, + int eeprom_offset, void *buf, int len) +{ + unsigned char *p = (unsigned char *) buf; + + // We setup a random read by first doing a "zero byte write". + // Writes carry an address. Reads use an implicit address. + + unsigned char cmd[1]; + cmd[0] = eeprom_offset; + if (!usrp_i2c_write (udh, i2c_addr, cmd, sizeof (cmd))) + return false; + + while (len > 0){ + int n = std::min (len, MAX_EP0_PKTSIZE); + if (!usrp_i2c_read (udh, i2c_addr, p, n)) + return false; + len -= n; + p += n; + } + return true; +} + +// ---------------------------------------------------------------- + +static bool +slot_to_codec (int slot, int *which_codec) +{ + *which_codec = 0; + + switch (slot){ + case SLOT_TX_A: + case SLOT_RX_A: + *which_codec = 0; + break; + + case SLOT_TX_B: + case SLOT_RX_B: + *which_codec = 1; + break; + + default: + fprintf (stderr, "usrp_prims:slot_to_codec: invalid slot = %d\n", slot); + return false; + } + return true; +} + +static bool +tx_slot_p (int slot) +{ + switch (slot){ + case SLOT_TX_A: + case SLOT_TX_B: + return true; + + default: + return false; + } +} + +bool +usrp_write_aux_dac (libusb_device_handle *udh, int slot, + int which_dac, int value) +{ + int which_codec; + + if (!slot_to_codec (slot, &which_codec)) + return false; + + if (!(0 <= which_dac && which_dac < 4)){ + fprintf (stderr, "usrp_write_aux_dac: invalid dac = %d\n", which_dac); + return false; + } + + value &= 0x0fff; // mask to 12-bits + + if (which_dac == 3){ + // dac 3 is really 12-bits. Use value as is. + bool r = true; + r &= usrp_9862_write (udh, which_codec, 43, (value >> 4)); // most sig + r &= usrp_9862_write (udh, which_codec, 42, (value & 0xf) << 4); // least sig + return r; + } + else { + // dac 0, 1, and 2 are really 8 bits. + value = value >> 4; // shift value appropriately + return usrp_9862_write (udh, which_codec, 36 + which_dac, value); + } +} + + +bool +usrp_read_aux_adc (libusb_device_handle *udh, int slot, + int which_adc, int *value) +{ + *value = 0; + int which_codec; + + if (!slot_to_codec (slot, &which_codec)) + return false; + + if (!(0 <= which_codec && which_codec < 2)){ + fprintf (stderr, "usrp_read_aux_adc: invalid adc = %d\n", which_adc); + return false; + } + + unsigned char aux_adc_control = + AUX_ADC_CTRL_REFSEL_A // on chip reference + | AUX_ADC_CTRL_REFSEL_B; // on chip reference + + int rd_reg = 26; // base address of two regs to read for result + + // program the ADC mux bits + if (tx_slot_p (slot)) + aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2; + else { + rd_reg += 2; + aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1; + } + + // I'm not sure if we can set the mux and issue a start conversion + // in the same cycle, so let's do them one at a time. + + usrp_9862_write (udh, which_codec, 34, aux_adc_control); + + if (which_adc == 0) + aux_adc_control |= AUX_ADC_CTRL_START_A; + else { + rd_reg += 4; + aux_adc_control |= AUX_ADC_CTRL_START_B; + } + + // start the conversion + usrp_9862_write (udh, which_codec, 34, aux_adc_control); + + // read the 10-bit result back + unsigned char v_lo = 0; + unsigned char v_hi = 0; + bool r = usrp_9862_read (udh, which_codec, rd_reg, &v_lo); + r &= usrp_9862_read (udh, which_codec, rd_reg + 1, &v_hi); + + if (r) + *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit + + return r; +} + +// ---------------------------------------------------------------- + +static int slot_to_i2c_addr (int slot) +{ + switch (slot){ + case SLOT_TX_A: return I2C_ADDR_TX_A; + case SLOT_RX_A: return I2C_ADDR_RX_A; + case SLOT_TX_B: return I2C_ADDR_TX_B; + case SLOT_RX_B: return I2C_ADDR_RX_B; + default: return -1; + } +} + +static void +set_chksum (unsigned char *buf) +{ + int sum = 0; + unsigned int i; + for (i = 0; i < DB_EEPROM_CLEN - 1; i++) + sum += buf[i]; + buf[i] = -sum; +} + +static usrp_dbeeprom_status_t +read_dboard_eeprom (libusb_device_handle *udh, + int slot_id, unsigned char *buf) +{ + int i2c_addr = slot_to_i2c_addr (slot_id); + if (i2c_addr == -1) + return UDBE_BAD_SLOT; + + if (!usrp_eeprom_read (udh, i2c_addr, 0, buf, DB_EEPROM_CLEN)) + return UDBE_NO_EEPROM; + + if (buf[DB_EEPROM_MAGIC] != DB_EEPROM_MAGIC_VALUE) + return UDBE_INVALID_EEPROM; + + int sum = 0; + for (unsigned int i = 0; i < DB_EEPROM_CLEN; i++) + sum += buf[i]; + + if ((sum & 0xff) != 0) + return UDBE_INVALID_EEPROM; + + return UDBE_OK; +} + +usrp_dbeeprom_status_t +usrp_read_dboard_eeprom (libusb_device_handle *udh, + int slot_id, usrp_dboard_eeprom *eeprom) +{ + unsigned char buf[DB_EEPROM_CLEN]; + + memset (eeprom, 0, sizeof (*eeprom)); + + usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); + if (s != UDBE_OK) + return s; + + eeprom->id = (buf[DB_EEPROM_ID_MSB] << 8) | buf[DB_EEPROM_ID_LSB]; + eeprom->oe = (buf[DB_EEPROM_OE_MSB] << 8) | buf[DB_EEPROM_OE_LSB]; + eeprom->offset[0] = (buf[DB_EEPROM_OFFSET_0_MSB] << 8) | buf[DB_EEPROM_OFFSET_0_LSB]; + eeprom->offset[1] = (buf[DB_EEPROM_OFFSET_1_MSB] << 8) | buf[DB_EEPROM_OFFSET_1_LSB]; + + return UDBE_OK; +} + +bool +usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, + short offset0, short offset1) +{ + unsigned char buf[DB_EEPROM_CLEN]; + + usrp_dbeeprom_status_t s = read_dboard_eeprom (udh, slot_id, buf); + if (s != UDBE_OK) + return false; + + buf[DB_EEPROM_OFFSET_0_LSB] = (offset0 >> 0) & 0xff; + buf[DB_EEPROM_OFFSET_0_MSB] = (offset0 >> 8) & 0xff; + buf[DB_EEPROM_OFFSET_1_LSB] = (offset1 >> 0) & 0xff; + buf[DB_EEPROM_OFFSET_1_MSB] = (offset1 >> 8) & 0xff; + set_chksum (buf); + + return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id), + 0, buf, sizeof (buf)); +} diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc new file mode 100644 index 000000000..841d447ae --- /dev/null +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -0,0 +1,490 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp/usrp_prims.h" +#include "usrp_commands.h" +#include "usrp_ids.h" +#include "usrp_i2c_addr.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include +#include +#include +#include +#include // FIXME should check with autoconf (nanosleep) +#include +#include +#include + +extern "C" { +#include "md5.h" +}; + +#define VERBOSE 0 + +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; + +static const int hash_slot_addr[2] = { + USRP_HASH_SLOT_0_ADDR, + USRP_HASH_SLOT_1_ADDR +}; + +static const char *default_firmware_filename = "std.ihx"; +static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; + +#include "std_paths.h" +#include + +void +usrp_one_time_init () +{ + static bool first = true; + + if (first){ + first = false; + usb_init (); // usb library init + usb_find_busses (); + usb_find_devices (); + } +} + +void +usrp_rescan () +{ + usb_find_busses (); + usb_find_devices (); +} + +// ---------------------------------------------------------------- + +/* + * q must be a real USRP, not an FX2. Return its hardware rev number. + */ +int +usrp_hw_rev (struct usb_device *q) +{ + return q->descriptor.bcdDevice & 0x00FF; +} + +/* + * q must be a real USRP, not an FX2. Return true if it's configured. + */ +static bool +_usrp_configured_p (struct usb_device *q) +{ + return (q->descriptor.bcdDevice & 0xFF00) != 0; +} + +bool +usrp_usrp_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_FSF + && q->descriptor.idProduct == USB_PID_FSF_USRP); +} + +bool +usrp_fx2_p (struct usb_device *q) +{ + return (q->descriptor.idVendor == USB_VID_CYPRESS + && q->descriptor.idProduct == USB_PID_CYPRESS_FX2); +} + +// ---------------------------------------------------------------- + +struct usb_device * +usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) +{ + struct usb_bus *p; + struct usb_device *q; + int n_found = 0; + + usrp_one_time_init (); + + p = usb_get_busses(); + while (p != NULL){ + q = p->devices; + while (q != NULL){ + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ + if (n_found == nth) // return this one + return q; + n_found++; // keep looking + } + q = q->next; + } + p = p->next; + } + return 0; // not found +} + +struct usb_dev_handle * +usrp_open_interface (struct usb_device *dev, int interface, int altinterface) +{ + struct usb_dev_handle *udh = usb_open (dev); + if (udh == 0) + return 0; + + if (dev != usb_device (udh)){ + fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); + abort (); + } + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + // There's no get get_configuration function, and with some of the newer kernels + // setting the configuration, even if to the same value, hoses any other processes + // that have it open. Hence we opt to not set it at all (We've only + // got a single configuration anyway). This may hose the win32 stuff... + + // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 + if (usb_set_configuration (udh, 1) < 0){ + /* + * Ignore this error. + * + * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that + * it returns -EBUSY if _any_ of the interfaces of a device are open. + * We've only got a single configuration, so setting it doesn't even seem + * like it should be required. + */ + } +#endif + + if (usb_claim_interface (udh, interface) < 0){ + fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); + fprintf (stderr, "%s\n", usb_strerror()); + usb_close (udh); + return 0; + } + + if (usb_set_altinterface (udh, altinterface) < 0){ + fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); + fprintf (stderr, "%s\n", usb_strerror()); + usb_release_interface (udh, interface); + usb_close (udh); + return 0; + } + + return udh; +} + +bool +usrp_close_interface (struct usb_dev_handle *udh) +{ + // we're assuming that closing an interface automatically releases it. + return usb_close (udh) == 0; +} + +// ---------------------------------------------------------------- +// write internal ram using Cypress vendor extension + +bool +write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, + int start_addr, size_t len) +{ + int addr; + int n; + int a; + int quanta = MAX_EP0_PKTSIZE; + + for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ + n = len + start_addr - addr; + if (n > quanta) + n = quanta; + + a = usb_control_msg (udh, 0x40, 0xA0, + addr, 0, (char *)(buf + (addr - start_addr)), n, 1000); + + if (a < 0){ + fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror()); + return false; + } + } + return true; +} + + +// ---------------------------------------------------------------- +// write vendor extension command to USRP + +int +write_cmd (struct usb_dev_handle *udh, + int request, int value, int index, + unsigned char *bytes, int len) +{ + int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; + + int r = usb_control_msg (udh, requesttype, request, value, index, + (char *) bytes, len, 1000); + if (r < 0){ + // we get EPIPE if the firmware stalls the endpoint. + if (errno != EPIPE) + fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ()); + } + + return r; +} + + +bool +usrp_set_hash (struct usb_dev_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware down load command to jam it in. + int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_get_hash (struct usb_dev_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware upload command to fetch it. + int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) +{ + switch (usrp_hw_rev (usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_write (udh, reg, value); + } +} + +bool +usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) +{ + switch (usrp_hw_rev (usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_read (udh, reg, value); + } +} + + + + +static usb_dev_handle * +open_nth_cmd_interface (int nth) +{ + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return 0; + } + + struct usb_dev_handle *udh; + + udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + // FIXME this could be because somebody else has it open. + // We should delay and retry... + fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); + usb_strerror (); + return 0; + } + + return udh; +} + + +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx){ + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return ULS_ERROR; + + usrp_load_status_t s = usrp_load_firmware (udh, filename, force); + usrp_close_interface (udh); + + switch (s){ + + case ULS_ALREADY_LOADED: // nothing changed... + return ULS_ALREADY_LOADED; + break; + + case ULS_OK: + // we loaded firmware successfully. + + // It's highly likely that the board will renumerate (simulate a + // disconnect/reconnect sequence), invalidating our current + // handle. + + // FIXME. Turn this into a loop that rescans until we refind ourselves + + struct timespec t; // delay for 1 second + t.tv_sec = 2; + t.tv_nsec = 0; + our_nanosleep (&t); + + usb_find_busses (); // rescan busses and devices + usb_find_devices (); + + return ULS_OK; + + default: + case ULS_ERROR: // some kind of problem + return ULS_ERROR; + } +} + +bool +usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename, + const std::string firmware_filename, + libusb_context *ctx) +{ + usrp_load_status_t s; + const char *filename; + const char *proto_filename; + int hw_rev; + + // first, figure out what hardware rev we're dealing with + { + struct usb_device *udev = usrp_find_device (nth); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return false; + } + hw_rev = usrp_hw_rev (udev); + } + + // start by loading the firmware + + proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", + default_firmware_filename); + filename = find_file(proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find firmware: %s\n", proto_filename); + return false; + } + + s = usrp_load_firmware_nth (nth, filename, force); + load_status_msg (s, "firmware", filename); + + if (s == ULS_ERROR) + return false; + + // if we actually loaded firmware, we must reload fpga ... + if (s == ULS_OK) + force = true; + + // now move on to the fpga configuration bitstream + + proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", + default_fpga_filename); + filename = find_file (proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); + return false; + } + + struct usb_dev_handle *udh = open_nth_cmd_interface (nth); + if (udh == 0) + return false; + + s = usrp_load_fpga (udh, filename, force); + usrp_close_interface (udh); + load_status_msg (s, "fpga bitstream", filename); + + if (s == ULS_ERROR) + return false; + + return true; +} + +void +power_down_9862s (struct usb_dev_handle *udh) +{ + static const unsigned char regs[] = { + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + }; + + switch (usrp_hw_rev (usb_device (udh))){ + case 0: + break; + + default: + usrp_9862_write_many_all (udh, regs, sizeof (regs)); + break; + } +} + + +std::string +usrp_serial_number(struct usb_dev_handle *udh) +{ + unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber; + if (iserial == 0) + return ""; + + char buf[1024]; + if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0) + return ""; + + return buf; +} -- cgit From f79de610d42fdbe8425a1a4aa3c04a1ee3c58e06 Mon Sep 17 00:00:00 2001 From: ttsou Date: Fri, 28 Aug 2009 11:42:41 -0400 Subject: Added libusb1 specific usrp_prims and usrp_basic --- usrp/host/lib/fusb_sysconfig_libusb1.cc | 9 +- usrp/host/lib/usrp_basic_libusb1.cc | 152 ++++++++++ usrp/host/lib/usrp_prims_libusb1.cc | 510 ++++++++++++++++++++++++++++++++ 3 files changed, 670 insertions(+), 1 deletion(-) create mode 100644 usrp/host/lib/usrp_basic_libusb1.cc create mode 100644 usrp/host/lib/usrp_prims_libusb1.cc (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index a005f540d..aafbb81cb 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -30,7 +30,14 @@ static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1 MB struct libusb_context; fusb_devhandle * -fusb_sysconfig::make_devhandle (libusb_device_handle *udh, libusb_context *ctx) +fusb_sysconfig::make_devhandle (libusb_device_handle *udh) +{ + return new fusb_devhandle_libusb1 (udh, NULL); +} + +fusb_devhandle * +fusb_sysconfig::make_devhandle (libusb_device_handle *udh, + libusb_context *ctx) { return new fusb_devhandle_libusb1 (udh, ctx); } diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc new file mode 100644 index 000000000..6c22b5c6f --- /dev/null +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -0,0 +1,152 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "usrp/usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include "fusb.h" +#include "db_boards.h" +#include +#include +#include +#include +#include +#include +#include + + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// These set the buffer size used for each end point using the fast +// usb interface. The kernel ends up locking down this much memory. + +static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); +static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; + + +static const double POLLING_INTERVAL = 0.1; // seconds + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// These settings give us: +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + +usrp_basic::usrp_basic (int which_board, + struct libusb_device_handle * + open_interface (struct libusb_device *dev), + const std::string fpga_filename, + const std::string firmware_filename) + : d_udh (0), d_ctx (0), + d_usb_data_rate (16000000), // SWAG, see below + d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), + d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) +{ + /* + * SWAG: Scientific Wild Ass Guess. + * + * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the + * actual rate. This doesn't change our throughput, that's determined by the signal + * processing code in the FPGA (which we know nothing about), and the system limits + * determined by libusb, fusb_*, and the underlying drivers. + */ + memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); + + d_ctx = usrp_one_time_init(true); + + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx)) + throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); + + struct libusb_device *dev = usrp_find_device (which_board, false, d_ctx); + if (dev == 0){ + fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); + throw std::runtime_error ("usrp_basic/usrp_find_device"); + } + + if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ + fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); + throw std::runtime_error ("usrp_basic/bad_rev"); + } + + if ((d_udh = open_interface (dev)) == 0) + throw std::runtime_error ("usrp_basic/open_interface"); + + // initialize registers that are common to rx and tx + + if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ + fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); + throw std::runtime_error ("usrp_basic/init_9862"); + } + + _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode + _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs + +} + +usrp_basic::~usrp_basic () +{ + // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} + + d_db.resize(0); // forget db shared ptrs + + if (d_udh) + libusb_close (d_udh); + + // Each object should be running in it's own context. If running in default + // (NULL) context then something went wrong. + + assert (d_ctx != NULL); + libusb_exit (d_ctx); +} + diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc new file mode 100644 index 000000000..3f0763bf9 --- /dev/null +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -0,0 +1,510 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp/usrp_prims.h" +#include "usrp_commands.h" +#include "usrp_ids.h" +#include "usrp_i2c_addr.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include +#include +#include +#include +#include +#include +#include +#include // FIXME should check with autoconf (nanosleep) +#include +#include +#include + +extern "C" { +#include "md5.h" +}; + +#define VERBOSE 0 + +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; + +static const int hash_slot_addr[2] = { + USRP_HASH_SLOT_0_ADDR, + USRP_HASH_SLOT_1_ADDR +}; + +static const char *default_firmware_filename = "std.ihx"; +static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; + +#include "std_paths.h" +#include + +libusb_context * +usrp_one_time_init (bool new_context) +{ + + static bool first = true; + libusb_context *ctx = NULL; + int ret; + + // On first call create default context in addition to any new requested + // context. The default context is probably useless in this form, but keep + // it for now due to compatibility reasons. + + if (first) { + first = false; + if ((ret = libusb_init (NULL)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); + } + + if (new_context) { + if ((ret = libusb_init (&ctx)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); + } + + return ctx; +} + +void +usrp_rescan () +{ + // nop +} + +// ---------------------------------------------------------------- + +/* + * q must be a real USRP, not an FX2. Return its hardware rev number. + */ +int +usrp_hw_rev (struct libusb_device *q) +{ + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return desc.bcdDevice & 0x00FF; +} + +/* + * q must be a real USRP, not an FX2. Return true if it's configured. + */ +static bool +_usrp_configured_p (struct libusb_device *q) +{ + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.bcdDevice & 0xFF00) != 0; +} + +bool +usrp_usrp_p (struct libusb_device *q) +{ + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.idVendor == USB_VID_FSF + && desc.idProduct == USB_PID_FSF_USRP); +} + +bool +usrp_fx2_p (struct libusb_device *q) +{ + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(q, &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + return (desc.idVendor == USB_VID_CYPRESS + && desc.idProduct == USB_PID_CYPRESS_FX2); +} + + +// ---------------------------------------------------------------- + +struct libusb_device * +usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) +{ + libusb_device **list; + + struct libusb_device *q; + int n_found = 0; + +//usrp_one_time_init (false); + assert (ctx != NULL); + + size_t cnt = libusb_get_device_list(ctx, &list); + size_t i = 0; + + if (cnt < 0) + fprintf(stderr, "usrp: libusb_get_device_list failed %d\n", cnt); + + for (i = 0; i < cnt; i++) { + q = list[i]; + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))) { + if (n_found == nth) // return this one + return q; + n_found++; // keep looking + } + } + +/* + * The list needs to be freed. Right now just release it if nothing is found. + */ + + libusb_free_device_list(list, 1); + + return 0; // not found +} + +struct libusb_device_handle * +usrp_open_interface (libusb_device *dev, int interface, int altinterface) +{ + struct libusb_device_handle *udh; + int ret; + + if (libusb_open (dev, &udh) < 0) + return 0; + + if (dev != libusb_get_device (udh)){ + fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); + abort (); + } + + if ((ret = libusb_claim_interface (udh, interface)) < 0) { + fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); + fprintf (stderr, "%d\n", ret); + libusb_close (udh); + return 0; + } + + if ((ret = libusb_set_interface_alt_setting (udh, interface, + altinterface)) < 0) { + fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); + fprintf (stderr, "%d\n", ret); + libusb_release_interface (udh, interface); + libusb_close (udh); + return 0; + } + + return udh; +} + +bool +usrp_close_interface (libusb_device_handle *udh) +{ + // returns void + libusb_close(udh); + return 0; +} + +// ---------------------------------------------------------------- +// write internal ram using Cypress vendor extension + +bool +write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf, + int start_addr, size_t len) +{ + int addr; + int n; + int a; + int quanta = MAX_EP0_PKTSIZE; + + for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ + n = len + start_addr - addr; + if (n > quanta) + n = quanta; + + a = libusb_control_transfer (udh, 0x40, 0xA0, + addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); + + if (a < 0){ + fprintf(stderr,"write_internal_ram failed: %u\n", a); + return false; + } + } + return true; +} + +// ---------------------------------------------------------------- +// write vendor extension command to USRP + +int +write_cmd (struct libusb_device_handle *udh, + int request, int value, int index, + unsigned char *bytes, int len) +{ + int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; + + int r = libusb_control_transfer(udh, requesttype, request, value, index, + (unsigned char *) bytes, len, 1000); + + if (r < 0){ + // we get EPIPE if the firmware stalls the endpoint. + if (r != LIBUSB_ERROR_PIPE) { + fprintf (stderr, "libusb_control_transfer failed: %i\n", r); + } + } + + return r; +} + +bool +usrp_set_hash (struct libusb_device_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware down load command to jam it in. + int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_get_hash (struct libusb_device_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware upload command to fetch it. + int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value) +{ + switch (usrp_hw_rev (libusb_get_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_write (udh, reg, value); + } +} + +bool +usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) +{ + switch (usrp_hw_rev (libusb_get_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_read (udh, reg, value); + } +} + + +static libusb_device_handle * +open_nth_cmd_interface (int nth, libusb_context *ctx) +{ + + struct libusb_device *udev = usrp_find_device (nth, false, ctx); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return 0; + } + + struct libusb_device_handle *udh; + + udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + // FIXME this could be because somebody else has it open. + // We should delay and retry... + fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); + return 0; + } + + return udh; +} + +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx) +{ + struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); + if (udh == 0) + return ULS_ERROR; + + usrp_load_status_t s = usrp_load_firmware (udh, filename, force); + usrp_close_interface (udh); + + switch (s){ + + case ULS_ALREADY_LOADED: // nothing changed... + return ULS_ALREADY_LOADED; + break; + + case ULS_OK: + // we loaded firmware successfully. + + // It's highly likely that the board will renumerate (simulate a + // disconnect/reconnect sequence), invalidating our current + // handle. + + // FIXME. Turn this into a loop that rescans until we refind ourselves + + struct timespec t; // delay for 1 second + t.tv_sec = 2; + t.tv_nsec = 0; + our_nanosleep (&t); + + return ULS_OK; + + default: + case ULS_ERROR: // some kind of problem + return ULS_ERROR; + } +} + +bool +usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename, + const std::string firmware_filename, + libusb_context *ctx) +{ + usrp_load_status_t s; + const char *filename; + const char *proto_filename; + int hw_rev; + + assert (ctx != NULL); + + // first, figure out what hardware rev we're dealing with + { + struct libusb_device *udev = usrp_find_device (nth, false, ctx); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return false; + } + hw_rev = usrp_hw_rev (udev); + } + + // start by loading the firmware + + proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", + default_firmware_filename); + filename = find_file(proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find firmware: %s\n", proto_filename); + return false; + } + s = usrp_load_firmware_nth (nth, filename, force, ctx); + load_status_msg (s, "firmware", filename); + + if (s == ULS_ERROR) + return false; + + // if we actually loaded firmware, we must reload fpga ... + if (s == ULS_OK) + force = true; + + // now move on to the fpga configuration bitstream + + proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", + default_fpga_filename); + filename = find_file (proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); + return false; + } + struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); + if (udh == 0) + return false; + + s = usrp_load_fpga (udh, filename, force); + usrp_close_interface (udh); + load_status_msg (s, "fpga bitstream", filename); + + if (s == ULS_ERROR) + return false; + + return true; +} + +void +power_down_9862s (struct libusb_device_handle *udh) +{ + static const unsigned char regs[] = { + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + }; + + switch (usrp_hw_rev (libusb_get_device (udh))){ + case 0: + break; + + default: + usrp_9862_write_many_all (udh, regs, sizeof (regs)); + break; + } +} + + +// ---------------------------------------------------------------- + +std::string +usrp_serial_number(struct libusb_device_handle *udh) +{ + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + + unsigned char iserial = desc.iSerialNumber; + if (iserial == 0) + return ""; + + unsigned char buf[1024]; + if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0) + return ""; + + return (char*) buf; +} -- cgit 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 --- 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 +- 12 files changed, 1277 insertions(+), 1376 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 (limited to 'usrp/host') 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 From e6cb4a4c14d9aa92d024727965bd45e68c6620ce Mon Sep 17 00:00:00 2001 From: ttsou Date: Wed, 9 Sep 2009 14:46:57 -0400 Subject: Intermediate fix to simplify usrp_one_time_init api --- usrp/host/apps/usrper.cc | 9 ++++++--- usrp/host/include/usrp/usrp_prims.h.in | 4 ++-- usrp/host/lib/usrp_basic_libusb1.cc | 10 ++++++---- usrp/host/lib/usrp_prims_libusb.cc | 24 +++++++++++++++++++++++- usrp/host/lib/usrp_prims_libusb1.cc | 21 ++++++++++++++++++++- 5 files changed, 57 insertions(+), 11 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc index 9c6403c9d..f8e98341f 100644 --- a/usrp/host/apps/usrper.cc +++ b/usrp/host/apps/usrper.cc @@ -19,6 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -34,7 +38,6 @@ char *prog_name; - static void set_progname (char *path) { @@ -191,10 +194,10 @@ main (int argc, char **argv) const char *cmd = argv[optind++]; nopts--; - libusb_context *ctx = usrp_one_time_init (true); + usrp_one_time_init (); - struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p, ctx); + struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p); if (udev == 0){ fprintf (stderr, "%s: failed to find usrp[%d]\n", prog_name, which_board); exit (1); diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index 5e3df3389..bf71e3b88 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -11,9 +11,9 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; * 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 (); +//libusb_context* usrp_one_time_init (bool new_context); +void usrp_one_time_init (libusb_context **ctx = NULL); /* * force a rescan of the buses and devices diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc index 6c22b5c6f..b1e3a5e3e 100644 --- a/usrp/host/lib/usrp_basic_libusb1.cc +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -103,7 +103,8 @@ usrp_basic::usrp_basic (int which_board, */ memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); - d_ctx = usrp_one_time_init(true); +// d_ctx = usrp_one_time_init(true); + usrp_one_time_init (&d_ctx); if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx)) throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); @@ -144,9 +145,10 @@ usrp_basic::~usrp_basic () libusb_close (d_udh); // Each object should be running in it's own context. If running in default - // (NULL) context then something went wrong. + // context then leave the instance open as it may be shared. This might + // occur in mixed libusb-0.12 and libusb-1.0 environments. - assert (d_ctx != NULL); - libusb_exit (d_ctx); + if (d_ctx != NULL) + libusb_exit (d_ctx); } diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc index 716e9fd70..4c826fa55 100644 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -64,12 +64,34 @@ static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; #include "std_paths.h" #include +/* void usrp_one_time_init () { static bool first = true; - if (first){ + if (first) { + first = false; + usb_init (); // usb library init + usb_find_busses (); + usb_find_devices (); + } +} + +libusb_context * +usrp_one_time_init (bool new_context) +{ + usrp_one_time_init (); + return NULL; +} +*/ + +void +usrp_one_time_init (libusb_context **ctx) +{ + static bool first = true; + + if (first) { first = false; usb_init (); // usb library init usb_find_busses (); diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index a99adafb3..d75430fe3 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -64,6 +64,24 @@ static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; #include "std_paths.h" #include +/* +void +usrp_one_time_init () +{ + usrp_one_time_init (false); +} +*/ + +void +usrp_one_time_init (libusb_context **ctx) +{ + int ret; + + if ((ret = libusb_init (ctx)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); +} + +/* libusb_context * usrp_one_time_init (bool new_context) { @@ -74,7 +92,7 @@ usrp_one_time_init (bool new_context) // On first call create default context in addition to any new requested // context. The default context is probably useless in this form, but keep - // it for now due to compatibility reasons. + // it for now due to possible compatibility reasons. if (first) { first = false; @@ -89,6 +107,7 @@ usrp_one_time_init (bool new_context) return ctx; } +*/ void usrp_rescan () -- cgit From fff854782eb2fbfc2a49e07ed9941b3beccc3e83 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Wed, 9 Sep 2009 18:52:34 -0400 Subject: Fixed swig and usrp apps to work with libusb-0.12 and libusb-1.0 plus minor cleanup --- usrp/host/apps/usrper.cc | 11 +++-- usrp/host/lib/fusb_sysconfig_libusb1.cc | 2 +- usrp/host/lib/fusb_sysconfig_linux.cc | 2 +- usrp/host/swig/usrp_prims.i | 76 ++++++++++++++++----------------- 4 files changed, 47 insertions(+), 44 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc index f8e98341f..d1270589b 100644 --- a/usrp/host/apps/usrper.cc +++ b/usrp/host/apps/usrper.cc @@ -27,7 +27,6 @@ #include #include #include -#include /* needed for usb functions */ #include #include #include @@ -36,6 +35,12 @@ #include "usrp_spi_defs.h" #include +#ifdef HAVE_LIBUSB_1 +#include +#else +#include +#endif + char *prog_name; static void @@ -197,7 +202,7 @@ main (int argc, char **argv) usrp_one_time_init (); - struct libusb_device *udev = usrp_find_device (which_board, fx2_ok_p); + libusb_device *udev = usrp_find_device (which_board, fx2_ok_p); if (udev == 0){ fprintf (stderr, "%s: failed to find usrp[%d]\n", prog_name, which_board); exit (1); @@ -211,7 +216,7 @@ main (int argc, char **argv) fprintf (stderr, "%s: found unconfigured FX2; needs firmware.\n", prog_name); } - struct libusb_device_handle *udh = usrp_open_cmd_interface (udev); + libusb_device_handle *udh = usrp_open_cmd_interface (udev); if (udh == 0){ fprintf (stderr, "%s: failed to open_cmd_interface\n", prog_name); exit (1); diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index aafbb81cb..4cbb74132 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -32,7 +32,7 @@ struct libusb_context; fusb_devhandle * fusb_sysconfig::make_devhandle (libusb_device_handle *udh) { - return new fusb_devhandle_libusb1 (udh, NULL); + make_devhandle (udh, NULL); } fusb_devhandle * diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index 8f56f61e2..d4bbfea76 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -36,7 +36,7 @@ fusb_sysconfig::make_devhandle (usb_dev_handle *udh) fusb_devhandle * fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { - return new fusb_devhandle_linux (udh); + make_devhandle (udh); } int fusb_sysconfig::max_block_size () diff --git a/usrp/host/swig/usrp_prims.i b/usrp/host/swig/usrp_prims.i index a93d14cac..fd65c25ab 100644 --- a/usrp/host/swig/usrp_prims.i +++ b/usrp/host/swig/usrp_prims.i @@ -42,14 +42,12 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; -struct libusb_device_handle; -struct libusb_device; /*! * \brief initialize libusb; probe busses and devices. * Safe to call more than once. */ -struct libusb_context *usrp_one_time_init (bool new_context); +void usrp_one_time_init (libusb_context **ctx = NULL); void usrp_rescan (); @@ -63,17 +61,17 @@ void usrp_rescan (); * configured USRP (firmware loaded) * unconfigured Cypress FX2 (only if fx2_ok_p is true) */ -struct libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, struct libusb_context *ctx); +libusb_device *usrp_find_device (int nth, bool fx2_ok_p = false, libusb_context *ctx); -bool usrp_usrp_p (struct libusb_device *q); //< is this a USRP -bool usrp_usrp0_p (struct libusb_device *q); //< is this a USRP Rev 0 -bool usrp_usrp1_p (struct libusb_device *q); //< is this a USRP Rev 1 -bool usrp_usrp2_p (struct libusb_device *q); //< is this a USRP Rev 2 -int usrp_hw_rev (struct libusb_device *q); //< return h/w rev code -bool usrp_fx2_p (struct libusb_device *q); //< is this an unconfigured Cypress FX2 +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 (struct libusb_device *q); //< some kind of unconfigured USRP -bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configured USRP +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 @@ -84,14 +82,14 @@ bool usrp_configured_usrp_p (struct libusb_device *q); //< some kind of configur * If interface can't be opened, or is already claimed by some other * process, 0 is returned. */ -struct libusb_device_handle *usrp_open_cmd_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_rx_interface (struct libusb_device *dev); -struct libusb_device_handle *usrp_open_tx_interface (struct libusb_device *dev); +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 (struct libusb_device_handle *udh); +bool usrp_close_interface (libusb_device_handle *udh); /*! * \brief load intel hex format file into USRP/Cypress FX2 (8051). @@ -103,7 +101,7 @@ bool usrp_close_interface (struct libusb_device_handle *udh); */ usrp_load_status_t -usrp_load_firmware (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_firmware (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load intel hex format file into USRP FX2 (8051). @@ -122,7 +120,7 @@ usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_contex * \brief load fpga configuration bitstream */ usrp_load_status_t -usrp_load_fpga (struct libusb_device_handle *udh, const char *filename, bool force); +usrp_load_fpga (libusb_device_handle *udh, const char *filename, bool force); /*! * \brief load the regular firmware and fpga bitstream in the Nth USRP. @@ -136,12 +134,12 @@ bool usrp_load_standard_bits (int nth, bool force); %include -bool usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value); +bool usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value); %inline %{ int -usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg) +usrp_read_fpga_reg (libusb_device_handle *udh, int reg) { int value; bool ok = usrp_read_fpga_reg (udh, reg, &value); @@ -153,37 +151,37 @@ usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg) %} -bool usrp_set_fpga_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_enable (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_tx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_fpga_rx_reset (struct libusb_device_handle *udh, bool on); -bool usrp_set_led (struct libusb_device_handle *udh, int which, 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); +bool usrp_set_led (libusb_device_handle *udh, int which, bool on); -bool usrp_check_rx_overrun (struct libusb_device_handle *udh, bool *overrun_p); -bool usrp_check_tx_underrun (struct libusb_device_handle *udh, bool *underrun_p); +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 (struct libusb_device_handle *udh, int i2c_addr, +bool usrp_i2c_write (libusb_device_handle *udh, int i2c_addr, void *buf, int len); -bool usrp_i2c_read (struct libusb_device_handle *udh, int i2c_addr, +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 (struct libusb_device_handle *udh, +bool usrp_spi_write (libusb_device_handle *udh, int optional_header, int enables, int format, unsigned char *buf, int len); -bool usrp_spi_read (struct libusb_device_handle *udh, +bool usrp_spi_read (libusb_device_handle *udh, int optional_header, int enables, int format, unsigned char *buf, int len); -bool usrp_9862_write (struct libusb_device_handle *udh, +bool usrp_9862_write (libusb_device_handle *udh, int which_codec, // [0, 1] int regno, // [0, 63] int value); // [0, 255] @@ -191,7 +189,7 @@ bool usrp_9862_write (struct libusb_device_handle *udh, %inline %{ int -usrp_9862_read (struct libusb_device_handle *udh, int which_codec, int reg) +usrp_9862_read (libusb_device_handle *udh, int which_codec, int reg) { unsigned char value; bool ok = usrp_9862_read (udh, which_codec, reg, &value); @@ -206,7 +204,7 @@ usrp_9862_read (struct libusb_device_handle *udh, int which_codec, int reg) %inline %{ bool -usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, +usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, const std::string buf) { return usrp_eeprom_write (udh, i2c_addr, eeprom_offset, @@ -214,7 +212,7 @@ usrp_eeprom_write (struct libusb_device_handle *udh, int i2c_addr, } std::string -usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, +usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, int eeprom_offset, int len) { if (len <= 0) @@ -230,12 +228,12 @@ usrp_eeprom_read (struct libusb_device_handle *udh, int i2c_addr, %} -bool usrp_write_aux_dac (struct libusb_device_handle *uhd, int slot, +bool usrp_write_aux_dac (libusb_device_handle *uhd, int slot, int which_dac, int value); %inline %{ -int usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, int which_adc) +int usrp_read_aux_adc (libusb_device_handle *udh, int slot, int which_adc) { int value; bool ok = usrp_read_aux_adc (udh, slot, which_adc, &value); @@ -253,7 +251,7 @@ int usrp_read_aux_adc (struct libusb_device_handle *udh, int slot, int which_adc * Note that this only works on a configured usrp. * \returns non-zero length string iff successful. */ -std::string usrp_serial_number(struct libusb_device_handle *udh); +std::string usrp_serial_number(libusb_device_handle *udh); /*! * \brief usrp daughterboard id to name mapping -- cgit From e67bd8ae9773731c00d2636833a9120ed3cc2ec1 Mon Sep 17 00:00:00 2001 From: ttsou Date: Thu, 10 Sep 2009 14:23:10 -0400 Subject: Integrated more usrp_prims code --- usrp/host/include/usrp/usrp_prims.h.in | 23 +---- usrp/host/lib/usrp_prims_common.cc | 136 +++++++++++++++++++++++++- usrp/host/lib/usrp_prims_libusb.cc | 154 +---------------------------- usrp/host/lib/usrp_prims_libusb1.cc | 172 +-------------------------------- usrp/host/swig/usrp_prims.i | 4 +- 5 files changed, 144 insertions(+), 345 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index bf71e3b88..69f41e57d 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -12,7 +12,6 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; * 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 (libusb_context **ctx = NULL); /* @@ -258,34 +257,22 @@ bool usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, std::string usrp_serial_number(libusb_device_handle *udh); /* - * Static helper functions + * Internal 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/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index 5ef6503d5..af763acc2 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -70,7 +70,7 @@ static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; #include "std_paths.h" #include -char * +static char * find_file (const char *filename, int hw_rev) { const char **sp = std_paths; @@ -93,7 +93,7 @@ find_file (const char *filename, int hw_rev) return 0; } -const char * +static const char * get_proto_filename(const std::string user_filename, const char *env_var, const char *def) { if (user_filename.length() != 0) @@ -349,7 +349,7 @@ usrp_set_led (libusb_device_handle *udh, int which, bool on) } -bool +static bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on) { return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; @@ -497,7 +497,30 @@ usrp_load_fpga (libusb_device_handle *udh, _usrp_load_fpga); } -bool +static libusb_device_handle * +open_nth_cmd_interface (int nth, libusb_context *ctx) +{ + + libusb_device *udev = usrp_find_device (nth, false, ctx); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return 0; + } + + libusb_device_handle *udh; + + udh = usrp_open_cmd_interface (udev); + if (udh == 0){ + // FIXME this could be because somebody else has it open. + // We should delay and retry... + fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); + return 0; + } + + return udh; +} + +static bool our_nanosleep (const struct timespec *delay) { struct timespec new_delay = *delay; @@ -525,7 +548,46 @@ mdelay (int millisecs) return our_nanosleep (&ts); } -void + +usrp_load_status_t +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx) +{ + libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); + if (udh == 0) + return ULS_ERROR; + + usrp_load_status_t s = usrp_load_firmware (udh, filename, force); + usrp_close_interface (udh); + + switch (s){ + + case ULS_ALREADY_LOADED: // nothing changed... + return ULS_ALREADY_LOADED; + break; + + case ULS_OK: + // we loaded firmware successfully. + + // It's highly likely that the board will renumerate (simulate a + // disconnect/reconnect sequence), invalidating our current + // handle. + + // FIXME. Turn this into a loop that rescans until we refind ourselves + + struct timespec t; // delay for 1 second + t.tv_sec = 2; + t.tv_nsec = 0; + our_nanosleep (&t); + + return ULS_OK; + + default: + case ULS_ERROR: // some kind of problem + return ULS_ERROR; + } +} + +static void load_status_msg (usrp_load_status_t s, const char *type, const char *filename) { char *e = getenv("USRP_VERBOSE"); @@ -548,6 +610,70 @@ load_status_msg (usrp_load_status_t s, const char *type, const char *filename) } } +bool +usrp_load_standard_bits (int nth, bool force, + const std::string fpga_filename, + const std::string firmware_filename, + libusb_context *ctx) +{ + usrp_load_status_t s; + const char *filename; + const char *proto_filename; + int hw_rev; + + // first, figure out what hardware rev we're dealing with + { + libusb_device *udev = usrp_find_device (nth, false, ctx); + if (udev == 0){ + fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); + return false; + } + hw_rev = usrp_hw_rev (udev); + } + + // start by loading the firmware + + proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", + default_firmware_filename); + filename = find_file(proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find firmware: %s\n", proto_filename); + return false; + } + s = usrp_load_firmware_nth (nth, filename, force, ctx); + load_status_msg (s, "firmware", filename); + + if (s == ULS_ERROR) + return false; + + // if we actually loaded firmware, we must reload fpga ... + if (s == ULS_OK) + force = true; + + // now move on to the fpga configuration bitstream + + proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", + default_fpga_filename); + filename = find_file (proto_filename, hw_rev); + if (filename == 0){ + fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); + return false; + } + libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); + if (udh == 0) + return false; + + s = usrp_load_fpga (udh, filename, force); + usrp_close_interface (udh); + load_status_msg (s, "fpga bitstream", filename); + + if (s == ULS_ERROR) + return false; + + return true; +} + + bool _usrp_get_status (libusb_device_handle *udh, int which, bool *trouble) { diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc index 4c826fa55..9371fb0e2 100644 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -64,28 +64,6 @@ static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; #include "std_paths.h" #include -/* -void -usrp_one_time_init () -{ - static bool first = true; - - if (first) { - first = false; - usb_init (); // usb library init - usb_find_busses (); - usb_find_devices (); - } -} - -libusb_context * -usrp_one_time_init (bool new_context) -{ - usrp_one_time_init (); - return NULL; -} -*/ - void usrp_one_time_init (libusb_context **ctx) { @@ -323,137 +301,6 @@ usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) } - - -static usb_dev_handle * -open_nth_cmd_interface (int nth) -{ - struct usb_device *udev = usrp_find_device (nth); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return 0; - } - - struct usb_dev_handle *udh; - - udh = usrp_open_cmd_interface (udev); - if (udh == 0){ - // FIXME this could be because somebody else has it open. - // We should delay and retry... - fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); - usb_strerror (); - return 0; - } - - return udh; -} - - -usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx){ - struct usb_dev_handle *udh = open_nth_cmd_interface (nth); - if (udh == 0) - return ULS_ERROR; - - usrp_load_status_t s = usrp_load_firmware (udh, filename, force); - usrp_close_interface (udh); - - switch (s){ - - case ULS_ALREADY_LOADED: // nothing changed... - return ULS_ALREADY_LOADED; - break; - - case ULS_OK: - // we loaded firmware successfully. - - // It's highly likely that the board will renumerate (simulate a - // disconnect/reconnect sequence), invalidating our current - // handle. - - // FIXME. Turn this into a loop that rescans until we refind ourselves - - struct timespec t; // delay for 1 second - t.tv_sec = 2; - t.tv_nsec = 0; - our_nanosleep (&t); - - usb_find_busses (); // rescan busses and devices - usb_find_devices (); - - return ULS_OK; - - default: - case ULS_ERROR: // some kind of problem - return ULS_ERROR; - } -} - -bool -usrp_load_standard_bits (int nth, bool force, - const std::string fpga_filename, - const std::string firmware_filename, - libusb_context *ctx) -{ - usrp_load_status_t s; - const char *filename; - const char *proto_filename; - int hw_rev; - - // first, figure out what hardware rev we're dealing with - { - struct usb_device *udev = usrp_find_device (nth); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return false; - } - hw_rev = usrp_hw_rev (udev); - } - - // start by loading the firmware - - proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", - default_firmware_filename); - filename = find_file(proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find firmware: %s\n", proto_filename); - return false; - } - - s = usrp_load_firmware_nth (nth, filename, force); - load_status_msg (s, "firmware", filename); - - if (s == ULS_ERROR) - return false; - - // if we actually loaded firmware, we must reload fpga ... - if (s == ULS_OK) - force = true; - - // now move on to the fpga configuration bitstream - - proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", - default_fpga_filename); - filename = find_file (proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); - return false; - } - - struct usb_dev_handle *udh = open_nth_cmd_interface (nth); - if (udh == 0) - return false; - - s = usrp_load_fpga (udh, filename, force); - usrp_close_interface (udh); - load_status_msg (s, "fpga bitstream", filename); - - if (s == ULS_ERROR) - return false; - - return true; -} - void power_down_9862s (struct usb_dev_handle *udh) { @@ -473,6 +320,7 @@ power_down_9862s (struct usb_dev_handle *udh) } } +// ---------------------------------------------------------------- std::string usrp_serial_number(struct usb_dev_handle *udh) diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index d75430fe3..672974259 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -64,14 +64,6 @@ static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; #include "std_paths.h" #include -/* -void -usrp_one_time_init () -{ - usrp_one_time_init (false); -} -*/ - void usrp_one_time_init (libusb_context **ctx) { @@ -81,34 +73,6 @@ usrp_one_time_init (libusb_context **ctx) fprintf (stderr, "usrp: libusb_init failed %i\n", ret); } -/* -libusb_context * -usrp_one_time_init (bool new_context) -{ - - static bool first = true; - libusb_context *ctx = NULL; - int ret; - - // On first call create default context in addition to any new requested - // context. The default context is probably useless in this form, but keep - // it for now due to possible compatibility reasons. - - if (first) { - first = false; - if ((ret = libusb_init (NULL)) < 0) - fprintf (stderr, "usrp: libusb_init failed %i\n", ret); - } - - if (new_context) { - if ((ret = libusb_init (&ctx)) < 0) - fprintf (stderr, "usrp: libusb_init failed %i\n", ret); - } - - return ctx; -} -*/ - void usrp_rescan () { @@ -176,7 +140,9 @@ usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) struct libusb_device *q; int n_found = 0; -//usrp_one_time_init (false); + // Make sure not operating on default context. There are cases where operating + // with a single global (NULL) context may be preferable, so this check can be + // skipped if you know what you're doing. assert (ctx != NULL); size_t cnt = libusb_get_device_list(ctx, &list); @@ -194,10 +160,7 @@ usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) } } -/* - * The list needs to be freed. Right now just release it if nothing is found. - */ - + // The list needs to be freed. Right now just release it if nothing is found. libusb_free_device_list(list, 1); return 0; // not found @@ -206,7 +169,7 @@ usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) struct libusb_device_handle * usrp_open_interface (libusb_device *dev, int interface, int altinterface) { - struct libusb_device_handle *udh; + libusb_device_handle *udh; int ret; if (libusb_open (dev, &udh) < 0) @@ -344,131 +307,6 @@ usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) } -static libusb_device_handle * -open_nth_cmd_interface (int nth, libusb_context *ctx) -{ - - struct libusb_device *udev = usrp_find_device (nth, false, ctx); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return 0; - } - - struct libusb_device_handle *udh; - - udh = usrp_open_cmd_interface (udev); - if (udh == 0){ - // FIXME this could be because somebody else has it open. - // We should delay and retry... - fprintf (stderr, "open_nth_cmd_interface: open_cmd_interface failed\n"); - return 0; - } - - return udh; -} - -usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx) -{ - struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); - if (udh == 0) - return ULS_ERROR; - - usrp_load_status_t s = usrp_load_firmware (udh, filename, force); - usrp_close_interface (udh); - - switch (s){ - - case ULS_ALREADY_LOADED: // nothing changed... - return ULS_ALREADY_LOADED; - break; - - case ULS_OK: - // we loaded firmware successfully. - - // It's highly likely that the board will renumerate (simulate a - // disconnect/reconnect sequence), invalidating our current - // handle. - - // FIXME. Turn this into a loop that rescans until we refind ourselves - - struct timespec t; // delay for 1 second - t.tv_sec = 2; - t.tv_nsec = 0; - our_nanosleep (&t); - - return ULS_OK; - - default: - case ULS_ERROR: // some kind of problem - return ULS_ERROR; - } -} - -bool -usrp_load_standard_bits (int nth, bool force, - const std::string fpga_filename, - const std::string firmware_filename, - libusb_context *ctx) -{ - usrp_load_status_t s; - const char *filename; - const char *proto_filename; - int hw_rev; - - assert (ctx != NULL); - - // first, figure out what hardware rev we're dealing with - { - struct libusb_device *udev = usrp_find_device (nth, false, ctx); - if (udev == 0){ - fprintf (stderr, "usrp: failed to find usrp[%d]\n", nth); - return false; - } - hw_rev = usrp_hw_rev (udev); - } - - // start by loading the firmware - - proto_filename = get_proto_filename(firmware_filename, "USRP_FIRMWARE", - default_firmware_filename); - filename = find_file(proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find firmware: %s\n", proto_filename); - return false; - } - s = usrp_load_firmware_nth (nth, filename, force, ctx); - load_status_msg (s, "firmware", filename); - - if (s == ULS_ERROR) - return false; - - // if we actually loaded firmware, we must reload fpga ... - if (s == ULS_OK) - force = true; - - // now move on to the fpga configuration bitstream - - proto_filename = get_proto_filename(fpga_filename, "USRP_FPGA", - default_fpga_filename); - filename = find_file (proto_filename, hw_rev); - if (filename == 0){ - fprintf (stderr, "Can't find fpga bitstream: %s\n", proto_filename); - return false; - } - struct libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); - if (udh == 0) - return false; - - s = usrp_load_fpga (udh, filename, force); - usrp_close_interface (udh); - load_status_msg (s, "fpga bitstream", filename); - - if (s == ULS_ERROR) - return false; - - return true; -} void power_down_9862s (struct libusb_device_handle *udh) diff --git a/usrp/host/swig/usrp_prims.i b/usrp/host/swig/usrp_prims.i index fd65c25ab..0476858da 100644 --- a/usrp/host/swig/usrp_prims.i +++ b/usrp/host/swig/usrp_prims.i @@ -61,7 +61,7 @@ void usrp_rescan (); * 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); +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 @@ -114,7 +114,7 @@ usrp_load_firmware (libusb_device_handle *udh, const char *filename, bool force) * then rescans the busses and devices. */ usrp_load_status_t -usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx); +usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_context *ctx = NULL); /*! * \brief load fpga configuration bitstream -- cgit From 98b30a4fc683d91458ccaefeaafbc8f4b783d17e Mon Sep 17 00:00:00 2001 From: ttsou Date: Thu, 10 Sep 2009 15:08:16 -0400 Subject: Use default arguments instead of overloaded virtual constructors for cleaner interface --- usrp/host/lib/fusb.h | 4 +--- usrp/host/lib/fusb_sysconfig_libusb1.cc | 6 ------ usrp/host/lib/fusb_sysconfig_linux.cc | 6 ------ 3 files changed, 1 insertion(+), 15 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index dbfda5a61..00bdffcc0 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -127,9 +127,7 @@ public: * \brief returns fusb_devhandle or throws if trouble */ static fusb_devhandle *make_devhandle (libusb_device_handle *udh, - libusb_context *ctx); - - static fusb_devhandle *make_devhandle (libusb_device_handle *udh); + libusb_context *ctx = 0); /*! * \brief Returns max block size in bytes (hard limit). diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index 4cbb74132..f71e34fa9 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -29,12 +29,6 @@ static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1 MB struct libusb_context; -fusb_devhandle * -fusb_sysconfig::make_devhandle (libusb_device_handle *udh) -{ - make_devhandle (udh, NULL); -} - fusb_devhandle * fusb_sysconfig::make_devhandle (libusb_device_handle *udh, libusb_context *ctx) diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index d4bbfea76..5b9bfb24a 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -27,12 +27,6 @@ static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit static const int DEFAULT_BLOCK_SIZE = 4 * 1024; // fewer kernel memory problems static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1MB -fusb_devhandle * -fusb_sysconfig::make_devhandle (usb_dev_handle *udh) -{ - return new fusb_devhandle_linux (udh); -} - fusb_devhandle * fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { -- cgit From c6f6e69024bd21e99f5f8673dce2399c4bfd8bb8 Mon Sep 17 00:00:00 2001 From: U-CERVELO\ttsou Date: Fri, 11 Sep 2009 15:35:28 -0400 Subject: changes to build on windows / cygwin --- usrp/host/lib/Makefile.am | 5 ++++- usrp/host/lib/fusb.cc | 6 +++--- usrp/host/lib/fusb.h | 2 +- usrp/host/lib/fusb_sysconfig_win32.cc | 2 +- usrp/host/lib/fusb_win32.cc | 6 +++--- usrp/host/lib/usrp_basic_common.cc | 6 +++--- usrp/host/lib/usrp_basic_libusb.cc | 6 +++--- 7 files changed, 18 insertions(+), 15 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 4dd47595e..7c5dc25a5 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -74,7 +74,10 @@ darwin_CODE = \ win32_CODE = \ fusb_win32.cc \ - fusb_sysconfig_win32.cc + fusb_sysconfig_win32.cc \ + usrp_prims_libusb.cc \ + usrp_basic_libusb.cc + linux_CODE = \ fusb_linux.cc \ diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc index ce4bb7aa9..0bd9ded59 100644 --- a/usrp/host/lib/fusb.cc +++ b/usrp/host/lib/fusb.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 00bdffcc0..341e570a4 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -65,7 +65,7 @@ public: int block_size = 0, int nblocks = 0) = 0; // ACCESSORS - libusb_device_handle *get_libusb_device_handle () const { return d_udh; } + libusb_device_handle *get_usb_dev_handle () const { return d_udh; } }; diff --git a/usrp/host/lib/fusb_sysconfig_win32.cc b/usrp/host/lib/fusb_sysconfig_win32.cc index 16eaaa645..a0d140543 100644 --- a/usrp/host/lib/fusb_sysconfig_win32.cc +++ b/usrp/host/lib/fusb_sysconfig_win32.cc @@ -27,7 +27,7 @@ static const int MAX_BLOCK_SIZE = 64 * 1024; // Windows kernel hard limit static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB fusb_devhandle * -fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { return new fusb_devhandle_win32 (udh); } diff --git a/usrp/host/lib/fusb_win32.cc b/usrp/host/lib/fusb_win32.cc index 8900576d9..7b11bb919 100644 --- a/usrp/host/lib/fusb_win32.cc +++ b/usrp/host/lib/fusb_win32.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include #include diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index 79e5b07ec..ad1eca56d 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include "usrp/usrp_basic.h" #include "usrp/usrp_prims.h" diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc index c788cc054..c4842cac9 100644 --- a/usrp/host/lib/usrp_basic_libusb.cc +++ b/usrp/host/lib/usrp_basic_libusb.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include #include "usrp/usrp_prims.h" -- cgit From 2c30dff7d519987a0f239f29f09e340d203c0148 Mon Sep 17 00:00:00 2001 From: ttsou Date: Sun, 13 Sep 2009 18:44:04 -0400 Subject: Fix glitch from previous commit --- usrp/host/lib/fusb_sysconfig_linux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index 5b9bfb24a..c2e453881 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -30,7 +30,7 @@ static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1MB fusb_devhandle * fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { - make_devhandle (udh); + return new fusb_devhandle_linux (udh); } int fusb_sysconfig::max_block_size () -- cgit From 0f03f1c1d460d865aeff91b9538266b0b210a357 Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 00:08:02 -0400 Subject: Combined additiona usrp_prims code --- usrp/host/include/usrp/usrp_prims.h.in | 17 +-- usrp/host/lib/usrp_basic_libusb.cc | 8 -- usrp/host/lib/usrp_basic_libusb1.cc | 13 +-- usrp/host/lib/usrp_prims_common.cc | 153 +++++++++++++++++++++++++-- usrp/host/lib/usrp_prims_libusb.cc | 173 +++++-------------------------- usrp/host/lib/usrp_prims_libusb1.cc | 184 +++++---------------------------- 6 files changed, 213 insertions(+), 335 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index 69f41e57d..ae12bbe65 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -260,19 +260,22 @@ std::string usrp_serial_number(libusb_device_handle *udh); * Internal 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 usrp1_fpga_write (libusb_device_handle *udh, int regno, int value); -bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value); +libusb_device_descriptor get_usb_device_descriptor (libusb_device *q); + +libusb_device *get_usb_device (libusb_device_handle *udh); + +int usb_control_transfer (struct usb_dev_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, + unsigned int timeout); +} + #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc index c4842cac9..bd22d6ad4 100644 --- a/usrp/host/lib/usrp_basic_libusb.cc +++ b/usrp/host/lib/usrp_basic_libusb.cc @@ -43,13 +43,6 @@ using namespace ad9862; #define NELEM(x) (sizeof (x) / sizeof (x[0])) -// These set the buffer size used for each end point using the fast -// usb interface. The kernel ends up locking down this much memory. - -static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); -static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); -static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; - static const double POLLING_INTERVAL = 0.1; // seconds @@ -65,7 +58,6 @@ static const double POLLING_INTERVAL = 0.1; // seconds // CLKIN = 64 MHz // CLKSEL pin = high // -// These settings give us: // CLKOUT1 = CLKIN = 64 MHz // CLKOUT2 = CLKIN = 64 MHz // ADC is clocked at 64 MHz diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc index b1e3a5e3e..64cff6078 100644 --- a/usrp/host/lib/usrp_basic_libusb1.cc +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -44,13 +44,6 @@ using namespace ad9862; #define NELEM(x) (sizeof (x) / sizeof (x[0])) -// These set the buffer size used for each end point using the fast -// usb interface. The kernel ends up locking down this much memory. - -static const int FUSB_BUFFER_SIZE = fusb_sysconfig::default_buffer_size(); -static const int FUSB_BLOCK_SIZE = fusb_sysconfig::max_block_size(); -static const int FUSB_NBLOCKS = FUSB_BUFFER_SIZE / FUSB_BLOCK_SIZE; - static const double POLLING_INTERVAL = 0.1; // seconds @@ -103,7 +96,6 @@ usrp_basic::usrp_basic (int which_board, */ memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); -// d_ctx = usrp_one_time_init(true); usrp_one_time_init (&d_ctx); if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename, d_ctx)) @@ -144,9 +136,8 @@ usrp_basic::~usrp_basic () if (d_udh) libusb_close (d_udh); - // Each object should be running in it's own context. If running in default - // context then leave the instance open as it may be shared. This might - // occur in mixed libusb-0.12 and libusb-1.0 environments. + // Each object _should_ be running in its own context. If running in default + // context then leave the instance open as it may be shared. if (d_ctx != NULL) libusb_exit (d_ctx); diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index af763acc2..1517d51ac 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -40,6 +40,7 @@ #include #include #include +#include "std_paths.h" #ifdef HAVE_LIBUSB_1 #include @@ -67,9 +68,6 @@ static const char *default_firmware_filename = "std.ihx"; static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; -#include "std_paths.h" -#include - static char * find_file (const char *filename, int hw_rev) { @@ -107,10 +105,48 @@ get_proto_filename(const std::string user_filename, const char *env_var, const c } -void power_down_9862s (libusb_device_handle *udh); +static void power_down_9862s (libusb_device_handle *udh); + // ---------------------------------------------------------------- +/* + * q must be a real USRP, not an FX2. Return its hardware rev number. + */ + +int +usrp_hw_rev (libusb_device *q) +{ + libusb_device_descriptor desc = get_usb_device_descriptor(q); + return desc.bcdDevice & 0x00FF; +} + +/* + * q must be a real USRP, not an FX2. Return true if it's configured. + */ +static bool +_usrp_configured_p (libusb_device *q) +{ + libusb_device_descriptor desc = get_usb_device_descriptor(q); + return (desc.bcdDevice & 0xFF00) != 0; +} + +bool +usrp_usrp_p (libusb_device *q) +{ + libusb_device_descriptor desc = get_usb_device_descriptor(q); + return (desc.idVendor == USB_VID_FSF + && desc.idProduct == USB_PID_FSF_USRP); +} + +bool +usrp_fx2_p (libusb_device *q) +{ + libusb_device_descriptor desc = get_usb_device_descriptor(q); + return (desc.idVendor == USB_VID_CYPRESS + && desc.idProduct == USB_PID_CYPRESS_FX2); +} + bool usrp_usrp0_p (libusb_device *q) { @@ -142,6 +178,10 @@ usrp_configured_usrp_p (libusb_device *q) return usrp_usrp_p (q) && _usrp_configured_p (q); } + +// ---------------------------------------------------------------- + + libusb_device_handle * usrp_open_cmd_interface (libusb_device *dev) { @@ -161,6 +201,35 @@ usrp_open_tx_interface (libusb_device *dev) } +// ---------------------------------------------------------------- +// write internal ram using Cypress vendor extension + +static bool +write_internal_ram (libusb_device_handle *udh, unsigned char *buf, + int start_addr, size_t len) +{ + int addr; + int n; + int a; + int quanta = MAX_EP0_PKTSIZE; + + for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ + n = len + start_addr - addr; + if (n > quanta) + n = quanta; + + a = usb_control_transfer (udh, 0x40, 0xA0, + addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); + + if (a < 0){ + fprintf(stderr,"write_internal_ram failed: %u\n", a); + return false; + } + } + return true; +} + + // ---------------------------------------------------------------- // whack the CPUCS register using the upload RAM vendor extension @@ -348,6 +417,31 @@ usrp_set_led (libusb_device_handle *udh, int which, bool on) return r == 0; } +bool +usrp_set_hash (libusb_device_handle *udh, int which, + const unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware down load command to jam it in. + int r = usb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + +bool +usrp_get_hash (libusb_device_handle *udh, int which, + unsigned char hash[USRP_HASH_SIZE]) +{ + which &= 1; + + // we use the Cypress firmware upload command to fetch it. + int r = usb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + (unsigned char *) hash, USRP_HASH_SIZE, 1000); + return r == USRP_HASH_SIZE; +} + + static bool usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on) @@ -355,7 +449,7 @@ usrp_set_switch (libusb_device_handle *udh, int cmd_byte, bool on) return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0; } -bool +static bool usrp1_fpga_write (libusb_device_handle *udh, int regno, int value) { @@ -374,7 +468,7 @@ usrp1_fpga_write (libusb_device_handle *udh, buf, sizeof (buf)); } -bool +static bool usrp1_fpga_read (libusb_device_handle *udh, int regno, int *value) { @@ -392,6 +486,29 @@ usrp1_fpga_read (libusb_device_handle *udh, return ok; } +bool +usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value) +{ + switch (usrp_hw_rev (get_usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_write (udh, reg, value); + } +} + +bool +usrp_read_fpga_reg (libusb_device_handle *udh, int reg, int *value) +{ + switch (usrp_hw_rev (get_usb_device (udh))){ + case 0: // not supported ;) + abort(); + + default: + return usrp1_fpga_read (udh, reg, value); + } +} bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on) @@ -814,6 +931,25 @@ usrp_9862_write_many_all (libusb_device_handle *udh, return result; } +static void +power_down_9862s (libusb_device_handle *udh) +{ + static const unsigned char regs[] = { + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + }; + + switch (usrp_hw_rev (get_usb_device (udh))){ + case 0: + break; + + default: + usrp_9862_write_many_all (udh, regs, sizeof (regs)); + break; + } +} + static const int EEPROM_PAGESIZE = 16; @@ -1077,3 +1213,8 @@ usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, return usrp_eeprom_write (udh, slot_to_i2c_addr (slot_id), 0, buf, sizeof (buf)); } + + + + + diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc index 9371fb0e2..d07caaa9d 100644 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -26,10 +26,7 @@ #include "usrp/usrp_prims.h" #include "usrp_commands.h" -#include "usrp_ids.h" -#include "usrp_i2c_addr.h" -#include "fpga_regs_common.h" -#include "fpga_regs_standard.h" +//#include "usrp_ids.h" #include #include #include @@ -37,8 +34,6 @@ #include #include #include -#include // FIXME should check with autoconf (nanosleep) -#include #include #include @@ -46,23 +41,33 @@ extern "C" { #include "md5.h" }; -#define VERBOSE 0 - using namespace ad9862; -static const int FIRMWARE_HASH_SLOT = 0; -static const int FPGA_HASH_SLOT = 1; +struct usb_device_descriptor +get_usb_device_descriptor (struct usb_device *q) +{ + return q->descriptor; +} -static const int hash_slot_addr[2] = { - USRP_HASH_SLOT_0_ADDR, - USRP_HASH_SLOT_1_ADDR -}; +struct usb_device * +get_usb_device (struct usb_dev_handle *udh) +{ + return usb_device (udh); +} -static const char *default_firmware_filename = "std.ihx"; -static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; +int +usb_control_transfer (struct usb_dev_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, unsigned int timeout) +{ + return usb_control_msg (udh, request_type, request, value, index, + (char*) *data, length, (int) timeout); + +} + + +// ---------------------------------------------------------------- -#include "std_paths.h" -#include void usrp_one_time_init (libusb_context **ctx) @@ -84,42 +89,10 @@ usrp_rescan () usb_find_devices (); } -// ---------------------------------------------------------------- - -/* - * q must be a real USRP, not an FX2. Return its hardware rev number. - */ -int -usrp_hw_rev (struct usb_device *q) -{ - return q->descriptor.bcdDevice & 0x00FF; -} - -/* - * q must be a real USRP, not an FX2. Return true if it's configured. - */ -bool -_usrp_configured_p (struct usb_device *q) -{ - return (q->descriptor.bcdDevice & 0xFF00) != 0; -} - -bool -usrp_usrp_p (struct usb_device *q) -{ - return (q->descriptor.idVendor == USB_VID_FSF - && q->descriptor.idProduct == USB_PID_FSF_USRP); -} - -bool -usrp_fx2_p (struct usb_device *q) -{ - return (q->descriptor.idVendor == USB_VID_CYPRESS - && q->descriptor.idProduct == USB_PID_CYPRESS_FX2); -} // ---------------------------------------------------------------- + struct usb_device * usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) { @@ -201,38 +174,11 @@ usrp_close_interface (struct usb_dev_handle *udh) return usb_close (udh) == 0; } -// ---------------------------------------------------------------- -// write internal ram using Cypress vendor extension - -bool -write_internal_ram (struct usb_dev_handle *udh, unsigned char *buf, - int start_addr, size_t len) -{ - int addr; - int n; - int a; - int quanta = MAX_EP0_PKTSIZE; - - for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ - n = len + start_addr - addr; - if (n > quanta) - n = quanta; - - a = usb_control_msg (udh, 0x40, 0xA0, - addr, 0, (char *)(buf + (addr - start_addr)), n, 1000); - - if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %s\n", usb_strerror()); - return false; - } - } - return true; -} - // ---------------------------------------------------------------- // write vendor extension command to USRP + int write_cmd (struct usb_dev_handle *udh, int request, int value, int index, @@ -252,76 +198,9 @@ write_cmd (struct usb_dev_handle *udh, } -bool -usrp_set_hash (struct usb_dev_handle *udh, int which, - const unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware down load command to jam it in. - int r = usb_control_msg (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -bool -usrp_get_hash (struct usb_dev_handle *udh, int which, - unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware upload command to fetch it. - int r = usb_control_msg (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -bool -usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value) -{ - switch (usrp_hw_rev (usb_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_write (udh, reg, value); - } -} - -bool -usrp_read_fpga_reg (struct usb_dev_handle *udh, int reg, int *value) -{ - switch (usrp_hw_rev (usb_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_read (udh, reg, value); - } -} - - -void -power_down_9862s (struct usb_dev_handle *udh) -{ - static const unsigned char regs[] = { - REG_RX_PWR_DN, 0x01, // everything - REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both - REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled - }; - - switch (usrp_hw_rev (usb_device (udh))){ - case 0: - break; - - default: - usrp_9862_write_many_all (udh, regs, sizeof (regs)); - break; - } -} - // ---------------------------------------------------------------- + std::string usrp_serial_number(struct usb_dev_handle *udh) { diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index 672974259..5cea97d8b 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -41,97 +41,64 @@ #include #include #include +#include "std_paths.h" extern "C" { #include "md5.h" }; -#define VERBOSE 0 - using namespace ad9862; -static const int FIRMWARE_HASH_SLOT = 0; -static const int FPGA_HASH_SLOT = 1; - -static const int hash_slot_addr[2] = { - USRP_HASH_SLOT_0_ADDR, - USRP_HASH_SLOT_1_ADDR -}; - -static const char *default_firmware_filename = "std.ihx"; -static const char *default_fpga_filename = "std_2rxhb_2tx.rbf"; -#include "std_paths.h" -#include - -void -usrp_one_time_init (libusb_context **ctx) +struct libusb_device_descriptor +get_usb_device_descriptor(struct libusb_device *q) { int ret; + struct libusb_device_descriptor desc; - if ((ret = libusb_init (ctx)) < 0) - fprintf (stderr, "usrp: libusb_init failed %i\n", ret); + if ((ret = libusb_get_device_descriptor(q, &desc)) < 0) + fprintf (stderr, "usrp: libusb_get_device_descriptor failed %d\n", ret); + + return desc; } -void -usrp_rescan () +struct libusb_device * +get_usb_device (struct libusb_device_handle *udh) { - // nop + return libusb_get_device (udh); } -// ---------------------------------------------------------------- - -/* - * q must be a real USRP, not an FX2. Return its hardware rev number. - */ int -usrp_hw_rev (struct libusb_device *q) +usb_control_transfer (struct usb_dev_handle *udh, uint8_t request_type, + uint8_t request, uint16_t value, uint16_t index, + unsigned char *data, uint16_t length, + unsigned int timeout) { - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + return libusb_control_transfer (udh, request_type, request, value, index, + *data, length, timeout); - return desc.bcdDevice & 0x00FF; } -/* - * q must be a real USRP, not an FX2. Return true if it's configured. - */ -bool -_usrp_configured_p (struct libusb_device *q) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - return (desc.bcdDevice & 0xFF00) != 0; -} +// ---------------------------------------------------------------- -bool -usrp_usrp_p (struct libusb_device *q) + +void +usrp_one_time_init (libusb_context **ctx) { - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); + int ret; - return (desc.idVendor == USB_VID_FSF - && desc.idProduct == USB_PID_FSF_USRP); + if ((ret = libusb_init (ctx)) < 0) + fprintf (stderr, "usrp: libusb_init failed %i\n", ret); } -bool -usrp_fx2_p (struct libusb_device *q) +void +usrp_rescan () { - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(q, &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - return (desc.idVendor == USB_VID_CYPRESS - && desc.idProduct == USB_PID_CYPRESS_FX2); + // nop } -// ---------------------------------------------------------------- - struct libusb_device * usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) { @@ -207,37 +174,11 @@ usrp_close_interface (libusb_device_handle *udh) return 0; } -// ---------------------------------------------------------------- -// write internal ram using Cypress vendor extension - -bool -write_internal_ram (struct libusb_device_handle *udh, unsigned char *buf, - int start_addr, size_t len) -{ - int addr; - int n; - int a; - int quanta = MAX_EP0_PKTSIZE; - - for (addr = start_addr; addr < start_addr + (int) len; addr += quanta){ - n = len + start_addr - addr; - if (n > quanta) - n = quanta; - - a = libusb_control_transfer (udh, 0x40, 0xA0, - addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); - - if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %u\n", a); - return false; - } - } - return true; -} // ---------------------------------------------------------------- // write vendor extension command to USRP + int write_cmd (struct libusb_device_handle *udh, int request, int value, int index, @@ -258,75 +199,6 @@ write_cmd (struct libusb_device_handle *udh, return r; } -bool -usrp_set_hash (struct libusb_device_handle *udh, int which, - const unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware down load command to jam it in. - int r = libusb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -bool -usrp_get_hash (struct libusb_device_handle *udh, int which, - unsigned char hash[USRP_HASH_SIZE]) -{ - which &= 1; - - // we use the Cypress firmware upload command to fetch it. - int r = libusb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); - return r == USRP_HASH_SIZE; -} - -bool -usrp_write_fpga_reg (struct libusb_device_handle *udh, int reg, int value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_write (udh, reg, value); - } -} - -bool -usrp_read_fpga_reg (struct libusb_device_handle *udh, int reg, int *value) -{ - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: // not supported ;) - abort(); - - default: - return usrp1_fpga_read (udh, reg, value); - } -} - - - -void -power_down_9862s (struct libusb_device_handle *udh) -{ - static const unsigned char regs[] = { - REG_RX_PWR_DN, 0x01, // everything - REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both - REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled - }; - - switch (usrp_hw_rev (libusb_get_device (udh))){ - case 0: - break; - - default: - usrp_9862_write_many_all (udh, regs, sizeof (regs)); - break; - } -} - // ---------------------------------------------------------------- -- cgit From 55e8ef7a4f94e7b6562ed29626a578cca1fcec34 Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 01:16:52 -0400 Subject: Fixed bug usb_control_transfer bug --- usrp/host/include/usrp/usrp_prims.h.in | 2 -- usrp/host/lib/usrp_prims_common.cc | 8 ++++---- usrp/host/lib/usrp_prims_libusb.cc | 6 +++--- 3 files changed, 7 insertions(+), 9 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index ae12bbe65..49a9d3d62 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -275,7 +275,5 @@ int usb_control_transfer (struct usb_dev_handle *udh, int request_type, int request, int value, int index, unsigned char *data, int length, unsigned int timeout); -} - #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index 1517d51ac..c71ba90b0 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -218,8 +218,8 @@ write_internal_ram (libusb_device_handle *udh, unsigned char *buf, if (n > quanta) n = quanta; - a = usb_control_transfer (udh, 0x40, 0xA0, - addr, 0, (unsigned char *)(buf + (addr - start_addr)), n, 1000); + a = usb_control_transfer (udh, 0x40, 0xA0, addr, 0, + (unsigned char*)(buf + (addr - start_addr)), n, 1000); if (a < 0){ fprintf(stderr,"write_internal_ram failed: %u\n", a); @@ -425,7 +425,7 @@ usrp_set_hash (libusb_device_handle *udh, int which, // we use the Cypress firmware down load command to jam it in. int r = usb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); + (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } @@ -437,7 +437,7 @@ usrp_get_hash (libusb_device_handle *udh, int which, // we use the Cypress firmware upload command to fetch it. int r = usb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, - (unsigned char *) hash, USRP_HASH_SIZE, 1000); + (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc index d07caaa9d..999dc5897 100644 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ b/usrp/host/lib/usrp_prims_libusb.cc @@ -26,7 +26,6 @@ #include "usrp/usrp_prims.h" #include "usrp_commands.h" -//#include "usrp_ids.h" #include #include #include @@ -60,8 +59,9 @@ usb_control_transfer (struct usb_dev_handle *udh, int request_type, int request, int value, int index, unsigned char *data, int length, unsigned int timeout) { - return usb_control_msg (udh, request_type, request, value, index, - (char*) *data, length, (int) timeout); + return usb_control_msg (udh, request_type, + request, value, index, + (char*) data, length, (int) timeout); } -- cgit From 68b0364367f8d99a34f0c38e8a0db0a290f297fc Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 14:43:37 -0400 Subject: Commonized more usrp_prims code and renamed libusb-0.12 files to libusb0 --- usrp/host/include/usrp/usrp_prims.h.in | 28 +++-- usrp/host/lib/Makefile.am | 8 +- usrp/host/lib/fusb.h | 6 +- usrp/host/lib/fusb_libusb1.cc | 6 +- usrp/host/lib/fusb_linux.cc | 6 +- usrp/host/lib/usrp_basic_libusb.cc | 137 --------------------- usrp/host/lib/usrp_basic_libusb0.cc | 137 +++++++++++++++++++++ usrp/host/lib/usrp_prims_common.cc | 45 ++++--- usrp/host/lib/usrp_prims_libusb.cc | 216 --------------------------------- usrp/host/lib/usrp_prims_libusb0.cc | 207 +++++++++++++++++++++++++++++++ usrp/host/lib/usrp_prims_libusb1.cc | 48 +++----- 11 files changed, 425 insertions(+), 419 deletions(-) delete mode 100644 usrp/host/lib/usrp_basic_libusb.cc create mode 100644 usrp/host/lib/usrp_basic_libusb0.cc delete mode 100644 usrp/host/lib/usrp_prims_libusb.cc create mode 100644 usrp/host/lib/usrp_prims_libusb0.cc (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index 49a9d3d62..7f5457afc 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -260,20 +260,26 @@ std::string usrp_serial_number(libusb_device_handle *udh); * Internal functions */ -libusb_device_handle *usrp_open_interface(libusb_device *dev, - int interface, - int altinterface); +libusb_device_handle * +usrp_open_interface(libusb_device *dev, int interface, int altinterface); -int write_cmd (libusb_device_handle *udh, int request, int value, - int index, unsigned char *bytes, int len); +int write_cmd (libusb_device_handle *udh, int request, int value, int index, + unsigned char *bytes, int len); -libusb_device_descriptor get_usb_device_descriptor (libusb_device *q); +/* + * Compatibility functions + */ + +libusb_device *_get_usb_device (libusb_device_handle *udh); + +libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); -libusb_device *get_usb_device (libusb_device_handle *udh); +int _get_usb_string_descriptor (libusb_device_handle *udh, int index, + unsigned char* data, int length); -int usb_control_transfer (struct usb_dev_handle *udh, int request_type, - int request, int value, int index, - unsigned char *data, int length, - unsigned int timeout); +int _usb_control_transfer (struct usb_dev_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, + unsigned int timeout); #endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 7c5dc25a5..7455b1536 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -75,15 +75,15 @@ darwin_CODE = \ win32_CODE = \ fusb_win32.cc \ fusb_sysconfig_win32.cc \ - usrp_prims_libusb.cc \ - usrp_basic_libusb.cc + usrp_prims_libusb0.cc \ + usrp_basic_libusb0.cc linux_CODE = \ fusb_linux.cc \ fusb_sysconfig_linux.cc \ - usrp_prims_libusb.cc \ - usrp_basic_libusb.cc + usrp_prims_libusb0.cc \ + usrp_basic_libusb0.cc ra_wb_CODE = \ fusb_ra_wb.cc \ diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 341e570a4..2ff7dc89f 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -25,6 +25,10 @@ #ifndef _FUSB_H_ #define _FUSB_H_ +/* + * This is bad, but it works for now. The fusb header files are not installed. + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -33,7 +37,7 @@ struct libusb_device_handle; #else struct usb_dev_handle; -typedef struct usb_dev_handle libusb_device_handle; +typedef usb_dev_handle libusb_device_handle; #endif struct libusb_context; diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index e50e44081..9d79cfe52 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include #include diff --git a/usrp/host/lib/fusb_linux.cc b/usrp/host/lib/fusb_linux.cc index 6c484569f..0b3aaed71 100644 --- a/usrp/host/lib/fusb_linux.cc +++ b/usrp/host/lib/fusb_linux.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif #include #include // libusb header diff --git a/usrp/host/lib/usrp_basic_libusb.cc b/usrp/host/lib/usrp_basic_libusb.cc deleted file mode 100644 index bd22d6ad4..000000000 --- a/usrp/host/lib/usrp_basic_libusb.cc +++ /dev/null @@ -1,137 +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. - */ - -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif - -#include -#include "usrp/usrp_prims.h" -#include "usrp_interfaces.h" -#include "fpga_regs_common.h" -#include "fpga_regs_standard.h" -#include "fusb.h" -#include "db_boards.h" -#include -#include -#include -#include -#include -#include -#include - -using namespace ad9862; - -#define NELEM(x) (sizeof (x) / sizeof (x[0])) - - -static const double POLLING_INTERVAL = 0.1; // seconds - - -////////////////////////////////////////////////////////////////// -// -// usrp_basic -// -//////////////////////////////////////////////////////////////// - - -// Given: -// CLKIN = 64 MHz -// CLKSEL pin = high -// -// CLKOUT1 = CLKIN = 64 MHz -// CLKOUT2 = CLKIN = 64 MHz -// ADC is clocked at 64 MHz -// DAC is clocked at 128 MHz - -static unsigned char common_regs[] = { - REG_GENERAL, 0, - REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC - | DLL_MULT_2X - | DLL_FAST), - REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, - REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 -}; - - -usrp_basic::usrp_basic (int which_board, - struct usb_dev_handle * - open_interface (struct usb_device *dev), - const std::string fpga_filename, - const std::string firmware_filename) - : d_udh (0), - d_usb_data_rate (16000000), // SWAG, see below - d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), - d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) -{ - /* - * SWAG: Scientific Wild Ass Guess. - * - * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. - * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., - * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the - * actual rate. This doesn't change our throughput, that's determined by the signal - * processing code in the FPGA (which we know nothing about), and the system limits - * determined by libusb, fusb_*, and the underlying drivers. - */ - memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); - - usrp_one_time_init (); - - if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) - throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); - - struct usb_device *dev = usrp_find_device (which_board); - if (dev == 0){ - fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); - throw std::runtime_error ("usrp_basic/usrp_find_device"); - } - - if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ - fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); - throw std::runtime_error ("usrp_basic/bad_rev"); - } - - if ((d_udh = open_interface (dev)) == 0) - throw std::runtime_error ("usrp_basic/open_interface"); - - // initialize registers that are common to rx and tx - - if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ - fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); - throw std::runtime_error ("usrp_basic/init_9862"); - } - - _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode - _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs -} - -usrp_basic::~usrp_basic () -{ - // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} - - d_db.resize(0); // forget db shared ptrs - - if (d_udh) - usb_close (d_udh); -} - diff --git a/usrp/host/lib/usrp_basic_libusb0.cc b/usrp/host/lib/usrp_basic_libusb0.cc new file mode 100644 index 000000000..bd22d6ad4 --- /dev/null +++ b/usrp/host/lib/usrp_basic_libusb0.cc @@ -0,0 +1,137 @@ +/* -*- 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. + */ + +//#ifdef HAVE_CONFIG_H +//#include "config.h" +//#endif + +#include +#include "usrp/usrp_prims.h" +#include "usrp_interfaces.h" +#include "fpga_regs_common.h" +#include "fpga_regs_standard.h" +#include "fusb.h" +#include "db_boards.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace ad9862; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static const double POLLING_INTERVAL = 0.1; // seconds + + +////////////////////////////////////////////////////////////////// +// +// usrp_basic +// +//////////////////////////////////////////////////////////////// + + +// Given: +// CLKIN = 64 MHz +// CLKSEL pin = high +// +// CLKOUT1 = CLKIN = 64 MHz +// CLKOUT2 = CLKIN = 64 MHz +// ADC is clocked at 64 MHz +// DAC is clocked at 128 MHz + +static unsigned char common_regs[] = { + REG_GENERAL, 0, + REG_DLL, (DLL_DISABLE_INTERNAL_XTAL_OSC + | DLL_MULT_2X + | DLL_FAST), + REG_CLKOUT, CLKOUT2_EQ_DLL_OVER_2, + REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 +}; + + +usrp_basic::usrp_basic (int which_board, + struct usb_dev_handle * + open_interface (struct usb_device *dev), + const std::string fpga_filename, + const std::string firmware_filename) + : d_udh (0), + d_usb_data_rate (16000000), // SWAG, see below + d_bytes_per_poll ((int) (POLLING_INTERVAL * d_usb_data_rate)), + d_verbose (false), d_fpga_master_clock_freq(64000000), d_db(2) +{ + /* + * SWAG: Scientific Wild Ass Guess. + * + * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the + * actual rate. This doesn't change our throughput, that's determined by the signal + * processing code in the FPGA (which we know nothing about), and the system limits + * determined by libusb, fusb_*, and the underlying drivers. + */ + memset (d_fpga_shadows, 0, sizeof (d_fpga_shadows)); + + usrp_one_time_init (); + + if (!usrp_load_standard_bits (which_board, false, fpga_filename, firmware_filename)) + throw std::runtime_error ("usrp_basic/usrp_load_standard_bits"); + + struct usb_device *dev = usrp_find_device (which_board); + if (dev == 0){ + fprintf (stderr, "usrp_basic: can't find usrp[%d]\n", which_board); + throw std::runtime_error ("usrp_basic/usrp_find_device"); + } + + if (!(usrp_usrp_p(dev) && usrp_hw_rev(dev) >= 1)){ + fprintf (stderr, "usrp_basic: sorry, this code only works with USRP revs >= 1\n"); + throw std::runtime_error ("usrp_basic/bad_rev"); + } + + if ((d_udh = open_interface (dev)) == 0) + throw std::runtime_error ("usrp_basic/open_interface"); + + // initialize registers that are common to rx and tx + + if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){ + fprintf (stderr, "usrp_basic: failed to init common AD9862 regs\n"); + throw std::runtime_error ("usrp_basic/init_9862"); + } + + _write_fpga_reg (FR_MODE, 0); // ensure we're in normal mode + _write_fpga_reg (FR_DEBUG_EN, 0); // disable debug outputs +} + +usrp_basic::~usrp_basic () +{ + // shutdown_daughterboards(); // call from ~usrp_basic_{tx,rx} + + d_db.resize(0); // forget db shared ptrs + + if (d_udh) + usb_close (d_udh); +} + diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index c71ba90b0..c9fcf80df 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -67,7 +67,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"; - static char * find_file (const char *filename, int hw_rev) { @@ -117,7 +116,7 @@ static void power_down_9862s (libusb_device_handle *udh); int usrp_hw_rev (libusb_device *q) { - libusb_device_descriptor desc = get_usb_device_descriptor(q); + libusb_device_descriptor desc = _get_usb_device_descriptor(q); return desc.bcdDevice & 0x00FF; } @@ -127,14 +126,14 @@ usrp_hw_rev (libusb_device *q) static bool _usrp_configured_p (libusb_device *q) { - libusb_device_descriptor desc = get_usb_device_descriptor(q); + libusb_device_descriptor desc = _get_usb_device_descriptor(q); return (desc.bcdDevice & 0xFF00) != 0; } bool usrp_usrp_p (libusb_device *q) { - libusb_device_descriptor desc = get_usb_device_descriptor(q); + libusb_device_descriptor desc = _get_usb_device_descriptor(q); return (desc.idVendor == USB_VID_FSF && desc.idProduct == USB_PID_FSF_USRP); } @@ -142,7 +141,7 @@ usrp_usrp_p (libusb_device *q) bool usrp_fx2_p (libusb_device *q) { - libusb_device_descriptor desc = get_usb_device_descriptor(q); + libusb_device_descriptor desc = _get_usb_device_descriptor(q); return (desc.idVendor == USB_VID_CYPRESS && desc.idProduct == USB_PID_CYPRESS_FX2); } @@ -218,7 +217,7 @@ write_internal_ram (libusb_device_handle *udh, unsigned char *buf, if (n > quanta) n = quanta; - a = usb_control_transfer (udh, 0x40, 0xA0, addr, 0, + a = _usb_control_transfer (udh, 0x40, 0xA0, addr, 0, (unsigned char*)(buf + (addr - start_addr)), n, 1000); if (a < 0){ @@ -424,7 +423,7 @@ usrp_set_hash (libusb_device_handle *udh, int which, which &= 1; // we use the Cypress firmware down load command to jam it in. - int r = usb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, + int r = _usb_control_transfer (udh, 0x40, 0xa0, hash_slot_addr[which], 0, (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } @@ -436,7 +435,7 @@ usrp_get_hash (libusb_device_handle *udh, int which, which &= 1; // we use the Cypress firmware upload command to fetch it. - int r = usb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, + int r = _usb_control_transfer (udh, 0xc0, 0xa0, hash_slot_addr[which], 0, (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } @@ -489,7 +488,7 @@ usrp1_fpga_read (libusb_device_handle *udh, bool usrp_write_fpga_reg (libusb_device_handle *udh, int reg, int value) { - switch (usrp_hw_rev (get_usb_device (udh))){ + switch (usrp_hw_rev (_get_usb_device (udh))){ case 0: // not supported ;) abort(); @@ -501,7 +500,7 @@ 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) { - switch (usrp_hw_rev (get_usb_device (udh))){ + switch (usrp_hw_rev (_get_usb_device (udh))){ case 0: // not supported ;) abort(); @@ -935,12 +934,12 @@ static void power_down_9862s (libusb_device_handle *udh) { static const unsigned char regs[] = { - REG_RX_PWR_DN, 0x01, // everything - REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both - REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled + REG_RX_PWR_DN, 0x01, // everything + REG_TX_PWR_DN, 0x0f, // pwr dn digital and analog_both + REG_TX_MODULATOR, 0x00 // coarse & fine modulators disabled }; - switch (usrp_hw_rev (get_usb_device (udh))){ + switch (usrp_hw_rev (_get_usb_device (udh))){ case 0: break; @@ -1214,6 +1213,24 @@ usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, 0, buf, sizeof (buf)); } +// ---------------------------------------------------------------- + +std::string +usrp_serial_number(libusb_device_handle *udh) +{ + libusb_device_descriptor desc = + _get_usb_device_descriptor (_get_usb_device (udh)); + + unsigned char iserial = desc.iSerialNumber; + if (iserial == 0) + return ""; + + unsigned char buf[1024]; + if (_get_usb_string_descriptor (udh, iserial, buf, sizeof(buf)) < 0) + return ""; + + return (char*) buf; +} diff --git a/usrp/host/lib/usrp_prims_libusb.cc b/usrp/host/lib/usrp_prims_libusb.cc deleted file mode 100644 index 999dc5897..000000000 --- a/usrp/host/lib/usrp_prims_libusb.cc +++ /dev/null @@ -1,216 +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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "usrp/usrp_prims.h" -#include "usrp_commands.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" { -#include "md5.h" -}; - -using namespace ad9862; - -struct usb_device_descriptor -get_usb_device_descriptor (struct usb_device *q) -{ - return q->descriptor; -} - -struct usb_device * -get_usb_device (struct usb_dev_handle *udh) -{ - return usb_device (udh); -} - -int -usb_control_transfer (struct usb_dev_handle *udh, int request_type, - int request, int value, int index, - unsigned char *data, int length, unsigned int timeout) -{ - return usb_control_msg (udh, request_type, - request, value, index, - (char*) data, length, (int) timeout); - -} - - -// ---------------------------------------------------------------- - - -void -usrp_one_time_init (libusb_context **ctx) -{ - static bool first = true; - - if (first) { - first = false; - usb_init (); // usb library init - usb_find_busses (); - usb_find_devices (); - } -} - -void -usrp_rescan () -{ - usb_find_busses (); - usb_find_devices (); -} - - -// ---------------------------------------------------------------- - - -struct usb_device * -usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) -{ - struct usb_bus *p; - struct usb_device *q; - int n_found = 0; - - usrp_one_time_init (); - - p = usb_get_busses(); - while (p != NULL){ - q = p->devices; - while (q != NULL){ - if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ - if (n_found == nth) // return this one - return q; - n_found++; // keep looking - } - q = q->next; - } - p = p->next; - } - return 0; // not found -} - -struct usb_dev_handle * -usrp_open_interface (struct usb_device *dev, int interface, int altinterface) -{ - struct usb_dev_handle *udh = usb_open (dev); - if (udh == 0) - return 0; - - if (dev != usb_device (udh)){ - fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); - abort (); - } - -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) - // There's no get get_configuration function, and with some of the newer kernels - // setting the configuration, even if to the same value, hoses any other processes - // that have it open. Hence we opt to not set it at all (We've only - // got a single configuration anyway). This may hose the win32 stuff... - - // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 - if (usb_set_configuration (udh, 1) < 0){ - /* - * Ignore this error. - * - * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that - * it returns -EBUSY if _any_ of the interfaces of a device are open. - * We've only got a single configuration, so setting it doesn't even seem - * like it should be required. - */ - } -#endif - - if (usb_claim_interface (udh, interface) < 0){ - fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); - fprintf (stderr, "%s\n", usb_strerror()); - usb_close (udh); - return 0; - } - - if (usb_set_altinterface (udh, altinterface) < 0){ - fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); - fprintf (stderr, "%s\n", usb_strerror()); - usb_release_interface (udh, interface); - usb_close (udh); - return 0; - } - - return udh; -} - -bool -usrp_close_interface (struct usb_dev_handle *udh) -{ - // we're assuming that closing an interface automatically releases it. - return usb_close (udh) == 0; -} - - -// ---------------------------------------------------------------- -// write vendor extension command to USRP - - -int -write_cmd (struct usb_dev_handle *udh, - int request, int value, int index, - unsigned char *bytes, int len) -{ - int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; - - int r = usb_control_msg (udh, requesttype, request, value, index, - (char *) bytes, len, 1000); - if (r < 0){ - // we get EPIPE if the firmware stalls the endpoint. - if (errno != EPIPE) - fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ()); - } - - return r; -} - - -// ---------------------------------------------------------------- - - -std::string -usrp_serial_number(struct usb_dev_handle *udh) -{ - unsigned char iserial = usb_device(udh)->descriptor.iSerialNumber; - if (iserial == 0) - return ""; - - char buf[1024]; - if (usb_get_string_simple(udh, iserial, buf, sizeof(buf)) < 0) - return ""; - - return buf; -} diff --git a/usrp/host/lib/usrp_prims_libusb0.cc b/usrp/host/lib/usrp_prims_libusb0.cc new file mode 100644 index 000000000..7ff831064 --- /dev/null +++ b/usrp/host/lib/usrp_prims_libusb0.cc @@ -0,0 +1,207 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "usrp/usrp_prims.h" +#include "usrp_commands.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "md5.h" +}; + +using namespace ad9862; + +/* + * libusb 0.12 / 1.0 compatibility + */ + +struct usb_device * +_get_usb_device (struct usb_dev_handle *udh) +{ + return usb_device (udh); +} + +struct usb_device_descriptor +_get_usb_device_descriptor (struct usb_device *q) +{ + return q->descriptor; +} +int +_get_usb_string_descriptor (struct usb_dev_handle *udh, int index, + unsigned char* data, int length) +{ + return usb_get_string_simple (udh, index, (char*) data, length); +} + +int +_usb_control_transfer (struct usb_dev_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, unsigned int timeout) +{ + return usb_control_msg (udh, request_type,request, value, index, + (char*) data, length, (int) timeout); +} + + +// ---------------------------------------------------------------- + + +void +usrp_one_time_init (libusb_context **ctx) +{ + static bool first = true; + + if (first) { + first = false; + usb_init (); // usb library init + usb_find_busses (); + usb_find_devices (); + } +} + +void +usrp_rescan () +{ + usb_find_busses (); + usb_find_devices (); +} + + +// ---------------------------------------------------------------- + + +struct usb_device * +usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) +{ + struct usb_bus *p; + struct usb_device *q; + int n_found = 0; + + usrp_one_time_init (); + + p = usb_get_busses(); + while (p != NULL){ + q = p->devices; + while (q != NULL){ + if (usrp_usrp_p (q) || (fx2_ok_p && usrp_fx2_p (q))){ + if (n_found == nth) // return this one + return q; + n_found++; // keep looking + } + q = q->next; + } + p = p->next; + } + return 0; // not found +} + +struct usb_dev_handle * +usrp_open_interface (struct usb_device *dev, int interface, int altinterface) +{ + struct usb_dev_handle *udh = usb_open (dev); + if (udh == 0) + return 0; + + if (dev != usb_device (udh)){ + fprintf (stderr, "%s:%d: internal error!\n", __FILE__, __LINE__); + abort (); + } + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + // There's no get get_configuration function, and with some of the newer kernels + // setting the configuration, even if to the same value, hoses any other processes + // that have it open. Hence we opt to not set it at all (We've only + // got a single configuration anyway). This may hose the win32 stuff... + + // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 + if (usb_set_configuration (udh, 1) < 0){ + /* + * Ignore this error. + * + * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that + * it returns -EBUSY if _any_ of the interfaces of a device are open. + * We've only got a single configuration, so setting it doesn't even seem + * like it should be required. + */ + } +#endif + + if (usb_claim_interface (udh, interface) < 0){ + fprintf (stderr, "%s:usb_claim_interface: failed interface %d\n", __FUNCTION__,interface); + fprintf (stderr, "%s\n", usb_strerror()); + usb_close (udh); + return 0; + } + + if (usb_set_altinterface (udh, altinterface) < 0){ + fprintf (stderr, "%s:usb_set_alt_interface: failed\n", __FUNCTION__); + fprintf (stderr, "%s\n", usb_strerror()); + usb_release_interface (udh, interface); + usb_close (udh); + return 0; + } + + return udh; +} + +bool +usrp_close_interface (struct usb_dev_handle *udh) +{ + // we're assuming that closing an interface automatically releases it. + return usb_close (udh) == 0; +} + + +// ---------------------------------------------------------------- +// write vendor extension command to USRP + + +int +write_cmd (struct usb_dev_handle *udh, + int request, int value, int index, + unsigned char *bytes, int len) +{ + int requesttype = (request & 0x80) ? VRT_VENDOR_IN : VRT_VENDOR_OUT; + + int r = usb_control_msg (udh, requesttype, request, value, index, + (char *) bytes, len, 1000); + if (r < 0){ + // we get EPIPE if the firmware stalls the endpoint. + if (errno != EPIPE) + fprintf (stderr, "usb_control_msg failed: %s\n", usb_strerror ()); + } + + return r; +} + diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index 5cea97d8b..4ce81509b 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -49,9 +49,18 @@ extern "C" { using namespace ad9862; +/* + * libusb 0.12 / 1.0 compatibility + */ + +struct libusb_device * +_get_usb_device (struct libusb_device_handle *udh) +{ + return libusb_get_device (udh); +} struct libusb_device_descriptor -get_usb_device_descriptor(struct libusb_device *q) +_get_usb_device_descriptor(struct libusb_device *q) { int ret; struct libusb_device_descriptor desc; @@ -62,21 +71,20 @@ get_usb_device_descriptor(struct libusb_device *q) return desc; } -struct libusb_device * -get_usb_device (struct libusb_device_handle *udh) +int +_get_usb_string_descriptor (struct libusb_device_handle *udh, int index, + unsigned char* data, int length) { - return libusb_get_device (udh); + return libusb_get_string_descriptor_ascii (udh, (uint8_t) index, data, length); } int -usb_control_transfer (struct usb_dev_handle *udh, uint8_t request_type, - uint8_t request, uint16_t value, uint16_t index, - unsigned char *data, uint16_t length, - unsigned int timeout) +_usb_control_transfer (struct libusb_dev_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, unsigned int timeout) { return libusb_control_transfer (udh, request_type, request, value, index, - *data, length, timeout); - + data, length, timeout); } @@ -199,23 +207,3 @@ write_cmd (struct libusb_device_handle *udh, return r; } - -// ---------------------------------------------------------------- - -std::string -usrp_serial_number(struct libusb_device_handle *udh) -{ - struct libusb_device_descriptor desc; - if (libusb_get_device_descriptor(libusb_get_device(udh), &desc) < 0) - fprintf (stderr, "usrp: libusb_get_device_descriptor failed\n"); - - unsigned char iserial = desc.iSerialNumber; - if (iserial == 0) - return ""; - - unsigned char buf[1024]; - if (libusb_get_string_descriptor_ascii(udh, iserial, buf, sizeof(buf)) < 0) - return ""; - - return (char*) buf; -} -- cgit From dce6d742c364daedda2f6e79da09e552ee910ede Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 18:51:28 -0400 Subject: Fixed libusb1 configure bug, libusb1 updates for previous usrp_prims integration --- usrp/host/include/usrp/usrp_prims.h.in | 2 +- usrp/host/lib/fusb_libusb1.cc | 2 +- usrp/host/lib/usrp_prims_libusb1.cc | 13 +++---------- 3 files changed, 5 insertions(+), 12 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_prims.h.in b/usrp/host/include/usrp/usrp_prims.h.in index 7f5457afc..8198d1797 100644 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ b/usrp/host/include/usrp/usrp_prims.h.in @@ -277,7 +277,7 @@ libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); int _get_usb_string_descriptor (libusb_device_handle *udh, int index, unsigned char* data, int length); -int _usb_control_transfer (struct usb_dev_handle *udh, int request_type, +int _usb_control_transfer (libusb_device_handle *udh, int request_type, int request, int value, int index, unsigned char *data, int length, unsigned int timeout); diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 9d79cfe52..1be2fa2f1 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -105,7 +105,7 @@ alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, write_buffer = new unsigned char [buffer_length]; // We need the base class libusb_device_handle - libusb_device_handle *dev_handle = dh->get_libusb_device_handle(); + libusb_device_handle *dev_handle = dh->get_usb_dev_handle(); // Load the libusb_transfer for bulk transfer libusb_fill_bulk_transfer (lut, // transfer diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index 4ce81509b..b7eba87ea 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -26,10 +26,6 @@ #include "usrp/usrp_prims.h" #include "usrp_commands.h" -#include "usrp_ids.h" -#include "usrp_i2c_addr.h" -#include "fpga_regs_common.h" -#include "fpga_regs_standard.h" #include #include #include @@ -37,11 +33,8 @@ #include #include #include -#include // FIXME should check with autoconf (nanosleep) -#include #include #include -#include "std_paths.h" extern "C" { #include "md5.h" @@ -79,9 +72,9 @@ _get_usb_string_descriptor (struct libusb_device_handle *udh, int index, } int -_usb_control_transfer (struct libusb_dev_handle *udh, int request_type, - int request, int value, int index, - unsigned char *data, int length, unsigned int timeout) +_usb_control_transfer (struct libusb_device_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, unsigned int timeout) { return libusb_control_transfer (udh, request_type, request, value, index, data, length, timeout); -- cgit From 579c6354514d57d3f1881131203ba6bbd9648816 Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 19:50:26 -0400 Subject: Removed preprocessor declrs out of fusb.h and created separate fusb_libusb1_base.h --- usrp/host/lib/Makefile.am | 9 +- usrp/host/lib/fusb.cc | 11 ++- usrp/host/lib/fusb.h | 12 --- usrp/host/lib/fusb_libusb1.cc | 6 +- usrp/host/lib/fusb_libusb1.h | 2 +- usrp/host/lib/fusb_libusb1_base.h | 140 ++++++++++++++++++++++++++++++++ usrp/host/lib/fusb_linux.cc | 6 +- usrp/host/lib/fusb_sysconfig_libusb1.cc | 2 +- usrp/host/lib/fusb_win32.cc | 6 +- usrp/host/lib/usrp_basic_common.cc | 21 ++--- usrp/host/lib/usrp_basic_libusb0.cc | 6 +- usrp/host/lib/usrp_basic_libusb1.cc | 2 +- usrp/host/lib/usrp_prims_common.cc | 12 +-- 13 files changed, 186 insertions(+), 49 deletions(-) create mode 100644 usrp/host/lib/fusb_libusb1_base.h (limited to 'usrp/host') diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 7455b1536..3687aae72 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -61,7 +61,9 @@ BUILT_SOURCES += usrp_dbid.cc \ generic_CODE = \ fusb_generic.cc \ - fusb_sysconfig_generic.cc + fusb_sysconfig_generic.cc \ + usrp_prims_libusb0.cc \ + usrp_basic_libusb0.cc darwin_CODE = \ fusb_darwin.cc \ @@ -87,7 +89,9 @@ linux_CODE = \ ra_wb_CODE = \ fusb_ra_wb.cc \ - fusb_sysconfig_ra_wb.cc + fusb_sysconfig_ra_wb.cc \ + usrp_prims_libusb0.cc \ + usrp_basic_libusb0.cc libusb1_CODE = \ fusb_libusb1.cc \ @@ -162,6 +166,7 @@ noinst_HEADERS = \ db_boards.h \ db_util.h \ fusb.h \ + fusb_libusb1_base.h \ fusb_darwin.h \ fusb_generic.h \ fusb_linux.h \ diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc index 0bd9ded59..992e1a2e9 100644 --- a/usrp/host/lib/fusb.cc +++ b/usrp/host/lib/fusb.cc @@ -20,12 +20,15 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef HAVE_LIBUSB_1 +#include +#else #include - +#endif // ------------------------------------------------------------------------ // device handle diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 2ff7dc89f..506f396fa 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -25,20 +25,8 @@ #ifndef _FUSB_H_ #define _FUSB_H_ -/* - * This is bad, but it works for now. The fusb header files are not installed. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_LIBUSB_1 -struct libusb_device_handle; -#else struct usb_dev_handle; typedef usb_dev_handle libusb_device_handle; -#endif struct libusb_context; class fusb_ephandle; diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 1be2fa2f1..6ea760726 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h index 4bc49aafb..0257ac38a 100644 --- a/usrp/host/lib/fusb_libusb1.h +++ b/usrp/host/lib/fusb_libusb1.h @@ -23,7 +23,7 @@ #ifndef _FUSB_LIBUSB1_H_ #define _FUSB_LIBUSB1_H_ -#include +#include #include struct libusb_transfer; diff --git a/usrp/host/lib/fusb_libusb1_base.h b/usrp/host/lib/fusb_libusb1_base.h new file mode 100644 index 000000000..6a2436453 --- /dev/null +++ b/usrp/host/lib/fusb_libusb1_base.h @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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. + */ + +// Fast USB interface + +#ifndef _FUSB_LIBUSB1_BASE_H_ +#define _FUSB_LIBUSB1_BASE_H_ + +struct libusb_device_handle; +struct libusb_context; +class fusb_ephandle; + +/*! + * \brief abstract usb device handle + */ +class fusb_devhandle { +private: + // NOT IMPLEMENTED + fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor + fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator + +protected: + libusb_device_handle *d_udh; + +public: + // CREATORS + fusb_devhandle (libusb_device_handle *udh); + virtual ~fusb_devhandle (); + + // MANIPULATORS + + /*! + * \brief return an ephandle of the correct subtype + */ + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0) = 0; + + // ACCESSORS + libusb_device_handle *get_usb_dev_handle () const { return d_udh; } +}; + + +/*! + * \brief abstract usb end point handle + */ +class fusb_ephandle { +private: + // NOT IMPLEMENTED + fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor + fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator + +protected: + int d_endpoint; + bool d_input_p; + int d_block_size; + int d_nblocks; + bool d_started; + +public: + fusb_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle (); + + virtual bool start () = 0; //!< begin streaming i/o + virtual bool stop () = 0; //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes) = 0; + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes) = 0; + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion () = 0; + + /*! + * \brief returns current block size. + */ + int block_size () { return d_block_size; }; +}; + + +/*! + * \brief factory for creating concrete instances of the appropriate subtype. + */ +class fusb_sysconfig { +public: + /*! + * \brief returns fusb_devhandle or throws if trouble + */ + static fusb_devhandle *make_devhandle (libusb_device_handle *udh, + libusb_context *ctx = 0); + + /*! + * \brief Returns max block size in bytes (hard limit). + */ + static int max_block_size (); + + /*! + * \brief Returns default block size in bytes. + */ + static int default_block_size (); + + /*! + * \brief Returns the default buffer size in bytes. + */ + static int default_buffer_size (); + +}; + +#endif /*_FUSB_LIBUSB1_BASE_H_ */ + diff --git a/usrp/host/lib/fusb_linux.cc b/usrp/host/lib/fusb_linux.cc index 0b3aaed71..6c484569f 100644 --- a/usrp/host/lib/fusb_linux.cc +++ b/usrp/host/lib/fusb_linux.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include // libusb header diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index f71e34fa9..ab3c475d5 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include +#include #include static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit diff --git a/usrp/host/lib/fusb_win32.cc b/usrp/host/lib/fusb_win32.cc index 7b11bb919..8900576d9 100644 --- a/usrp/host/lib/fusb_win32.cc +++ b/usrp/host/lib/fusb_win32.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index ad1eca56d..9a1f9fd55 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -20,16 +20,23 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_LIBUSB_1 +#include "fusb_libusb1_base.h" +#include +#else +#include "fusb.h" +#include +#endif #include "usrp/usrp_basic.h" #include "usrp/usrp_prims.h" #include "usrp_interfaces.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" -#include "fusb.h" #include "db_boards.h" #include #include @@ -38,12 +45,6 @@ #include #include -#ifdef HAVE_LIBUSB_1 -#include -#else -#include -#endif - using namespace ad9862; #define NELEM(x) (sizeof (x) / sizeof (x[0])) diff --git a/usrp/host/lib/usrp_basic_libusb0.cc b/usrp/host/lib/usrp_basic_libusb0.cc index bd22d6ad4..6e41585bb 100644 --- a/usrp/host/lib/usrp_basic_libusb0.cc +++ b/usrp/host/lib/usrp_basic_libusb0.cc @@ -20,9 +20,9 @@ * Boston, MA 02110-1301, USA. */ -//#ifdef HAVE_CONFIG_H -//#include "config.h" -//#endif +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include #include "usrp/usrp_prims.h" diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc index 64cff6078..7cfd69be6 100644 --- a/usrp/host/lib/usrp_basic_libusb1.cc +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -29,7 +29,7 @@ #include "usrp_interfaces.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" -#include "fusb.h" +#include "fusb_libusb1_base.h" #include "db_boards.h" #include #include diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index c9fcf80df..41722b23b 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -24,6 +24,12 @@ #include "config.h" #endif +#ifdef HAVE_LIBUSB_1 +#include +#else +#include +#endif + #include "usrp/usrp_prims.h" #include "usrp_commands.h" #include "usrp_ids.h" @@ -42,12 +48,6 @@ #include #include "std_paths.h" -#ifdef HAVE_LIBUSB_1 -#include -#else -#include -#endif - extern "C" { #include "md5.h" }; -- cgit From 44269e7b15129102f93131269e7796fde70ddc05 Mon Sep 17 00:00:00 2001 From: ttsou Date: Mon, 14 Sep 2009 21:42:03 -0400 Subject: Moved to single generated fusb.h, headers now generated out of lib directory --- usrp/host/Makefile.am | 2 +- usrp/host/include/usrp/Makefile.am | 10 - usrp/host/include/usrp/usrp_basic.h.in | 960 -------------------------------- usrp/host/include/usrp/usrp_prims.h.in | 285 ---------- usrp/host/lib/Makefile.am | 33 +- usrp/host/lib/fusb.cc | 4 - usrp/host/lib/fusb.h | 141 ----- usrp/host/lib/fusb.h.in | 111 ++++ usrp/host/lib/fusb_libusb1.cc | 3 +- usrp/host/lib/fusb_libusb1.h | 2 +- usrp/host/lib/fusb_libusb1_base.h | 140 ----- usrp/host/lib/fusb_sysconfig_libusb1.cc | 2 +- usrp/host/lib/usrp_basic.h.in | 960 ++++++++++++++++++++++++++++++++ usrp/host/lib/usrp_basic_common.cc | 3 +- usrp/host/lib/usrp_basic_libusb1.cc | 2 +- usrp/host/lib/usrp_prims.h.in | 285 ++++++++++ 16 files changed, 1391 insertions(+), 1552 deletions(-) delete mode 100644 usrp/host/include/usrp/usrp_basic.h.in delete mode 100644 usrp/host/include/usrp/usrp_prims.h.in delete mode 100644 usrp/host/lib/fusb.h create mode 100644 usrp/host/lib/fusb.h.in delete mode 100644 usrp/host/lib/fusb_libusb1_base.h create mode 100644 usrp/host/lib/usrp_basic.h.in create mode 100644 usrp/host/lib/usrp_prims.h.in (limited to 'usrp/host') diff --git a/usrp/host/Makefile.am b/usrp/host/Makefile.am index cc4ba91aa..aa94fbd6e 100644 --- a/usrp/host/Makefile.am +++ b/usrp/host/Makefile.am @@ -19,7 +19,7 @@ # Boston, MA 02110-1301, USA. # -SUBDIRS = misc include lib apps +SUBDIRS = misc lib include apps if PYTHON SUBDIRS += swig diff --git a/usrp/host/include/usrp/Makefile.am b/usrp/host/include/usrp/Makefile.am index 1e36b105a..d580d8a75 100644 --- a/usrp/host/include/usrp/Makefile.am +++ b/usrp/host/include/usrp/Makefile.am @@ -23,16 +23,6 @@ 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.in b/usrp/host/include/usrp/usrp_basic.h.in deleted file mode 100644 index 3faa5304f..000000000 --- a/usrp/host/include/usrp/usrp_basic.h.in +++ /dev/null @@ -1,960 +0,0 @@ -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.in b/usrp/host/include/usrp/usrp_prims.h.in deleted file mode 100644 index 8198d1797..000000000 --- a/usrp/host/include/usrp/usrp_prims.h.in +++ /dev/null @@ -1,285 +0,0 @@ -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. - */ - -void usrp_one_time_init (libusb_context **ctx = NULL); - -/* - * 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); - -/* - * Internal functions - */ - -libusb_device_handle * -usrp_open_interface(libusb_device *dev, int interface, int altinterface); - -int write_cmd (libusb_device_handle *udh, int request, int value, int index, - unsigned char *bytes, int len); - -/* - * Compatibility functions - */ - -libusb_device *_get_usb_device (libusb_device_handle *udh); - -libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); - -int _get_usb_string_descriptor (libusb_device_handle *udh, int index, - unsigned char* data, int length); - -int _usb_control_transfer (libusb_device_handle *udh, int request_type, - int request, int value, int index, - unsigned char *data, int length, - unsigned int timeout); - -#endif /* _USRP_PRIMS_H_ */ diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 3687aae72..16f53bd38 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -44,10 +44,16 @@ endif EXTRA_DIST = \ std_paths.h.in \ - usrp_dbid.dat + usrp_dbid.dat \ + fusb.h.in \ + usrp_prims.h.in \ + usrp_basic.h.in BUILT_SOURCES = \ - $(abs_top_builddir)/usrp/host/include/usrp/usrp_dbid.h + $(abs_top_builddir)/usrp/host/include/usrp/usrp_dbid.h \ + fusb.h \ + usrp_prims.h \ + usrp_basic.h BUILT_SOURCES += usrp_dbid.cc \ usrp_dbid.py @@ -133,8 +139,6 @@ libusrp_la_common_SOURCES = \ db_dtt768.cc \ db_util.cc - - if FUSB_TECH_generic libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE) endif @@ -166,7 +170,6 @@ noinst_HEADERS = \ db_boards.h \ db_util.h \ fusb.h \ - fusb_libusb1_base.h \ fusb_darwin.h \ fusb_generic.h \ fusb_linux.h \ @@ -193,3 +196,23 @@ gen_sources = $(BUILT_SOURCES) gen_sources_deps = gen_usrp_dbid.py usrp_dbid.dat par_gen_command = PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat include $(top_srcdir)/Makefile.par.gen + + +# Generate libusb dependent header files from configure. +# These are already defined, but override them here, which throws warnings. +# Need to figure out how to separate rules for BUILD_SOURCES. +fusb.h: fusb.h.in $(top_srcdir)/config.status + cd $(top_srcdir) \ + && CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=fusb.h \ + $(SHELL) ./config.status + +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 + diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc index 992e1a2e9..c14d7c1fb 100644 --- a/usrp/host/lib/fusb.cc +++ b/usrp/host/lib/fusb.cc @@ -24,11 +24,7 @@ #include "config.h" #endif -#ifdef HAVE_LIBUSB_1 -#include -#else #include -#endif // ------------------------------------------------------------------------ // device handle diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h deleted file mode 100644 index 506f396fa..000000000 --- a/usrp/host/lib/fusb.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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. - */ - -// Fast USB interface - -#ifndef _FUSB_H_ -#define _FUSB_H_ - -struct usb_dev_handle; -typedef usb_dev_handle libusb_device_handle; - -struct libusb_context; -class fusb_ephandle; - -/*! - * \brief abstract usb device handle - */ -class fusb_devhandle { -private: - // NOT IMPLEMENTED - fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor - fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator - -protected: - libusb_device_handle *d_udh; - -public: - // CREATORS - fusb_devhandle (libusb_device_handle *udh); - virtual ~fusb_devhandle (); - - // MANIPULATORS - - /*! - * \brief return an ephandle of the correct subtype - */ - virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0) = 0; - - // ACCESSORS - libusb_device_handle *get_usb_dev_handle () const { return d_udh; } -}; - - -/*! - * \brief abstract usb end point handle - */ -class fusb_ephandle { -private: - // NOT IMPLEMENTED - fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor - fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator - -protected: - int d_endpoint; - bool d_input_p; - int d_block_size; - int d_nblocks; - bool d_started; - -public: - fusb_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0); - virtual ~fusb_ephandle (); - - virtual bool start () = 0; //!< begin streaming i/o - virtual bool stop () = 0; //!< stop streaming i/o - - /*! - * \returns \p nbytes if write was successfully enqueued, else -1. - * Will block if no free buffers available. - */ - virtual int write (const void *buffer, int nbytes) = 0; - - /*! - * \returns number of bytes read or -1 if error. - * number of bytes read will be <= nbytes. - * Will block if no input available. - */ - virtual int read (void *buffer, int nbytes) = 0; - - /* - * block until all outstanding writes have completed - */ - virtual void wait_for_completion () = 0; - - /*! - * \brief returns current block size. - */ - int block_size () { return d_block_size; }; -}; - - -/*! - * \brief factory for creating concrete instances of the appropriate subtype. - */ -class fusb_sysconfig { -public: - /*! - * \brief returns fusb_devhandle or throws if trouble - */ - static fusb_devhandle *make_devhandle (libusb_device_handle *udh, - libusb_context *ctx = 0); - - /*! - * \brief Returns max block size in bytes (hard limit). - */ - static int max_block_size (); - - /*! - * \brief Returns default block size in bytes. - */ - static int default_block_size (); - - /*! - * \brief Returns the default buffer size in bytes. - */ - static int default_buffer_size (); - -}; - -#endif /* _FUSB_H_ */ diff --git a/usrp/host/lib/fusb.h.in b/usrp/host/lib/fusb.h.in new file mode 100644 index 000000000..4a65d994f --- /dev/null +++ b/usrp/host/lib/fusb.h.in @@ -0,0 +1,111 @@ +struct libusb_context; +class fusb_ephandle; + +/*! + * \brief abstract usb device handle + */ +class fusb_devhandle { +private: + // NOT IMPLEMENTED + fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor + fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator + +protected: + libusb_device_handle *d_udh; + +public: + // CREATORS + fusb_devhandle (libusb_device_handle *udh); + virtual ~fusb_devhandle (); + + // MANIPULATORS + + /*! + * \brief return an ephandle of the correct subtype + */ + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0) = 0; + + // ACCESSORS + libusb_device_handle *get_usb_dev_handle () const { return d_udh; } +}; + + +/*! + * \brief abstract usb end point handle + */ +class fusb_ephandle { +private: + // NOT IMPLEMENTED + fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor + fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator + +protected: + int d_endpoint; + bool d_input_p; + int d_block_size; + int d_nblocks; + bool d_started; + +public: + fusb_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle (); + + virtual bool start () = 0; //!< begin streaming i/o + virtual bool stop () = 0; //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes) = 0; + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes) = 0; + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion () = 0; + + /*! + * \brief returns current block size. + */ + int block_size () { return d_block_size; }; +}; + + +/*! + * \brief factory for creating concrete instances of the appropriate subtype. + */ +class fusb_sysconfig { +public: + /*! + * \brief returns fusb_devhandle or throws if trouble + */ + static fusb_devhandle *make_devhandle (libusb_device_handle *udh, + libusb_context *ctx = 0); + + /*! + * \brief Returns max block size in bytes (hard limit). + */ + static int max_block_size (); + + /*! + * \brief Returns default block size in bytes. + */ + static int default_block_size (); + + /*! + * \brief Returns the default buffer size in bytes. + */ + static int default_buffer_size (); + +}; + +#endif /* _FUSB_H_ */ diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 6ea760726..0171235de 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -25,6 +25,7 @@ #endif #include +#include #include #include #include @@ -41,7 +42,7 @@ static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20); // 4 MB endpoint static const int LIBUSB_TIMEOUT = 0; // no timeout -inline static fusb_ephandle_libusb1* +inline static fusb_ephandle_libusb1 * lut_get_ephandle (libusb_transfer *lut) { return (fusb_ephandle_libusb1 *) lut->user_data; diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h index 0257ac38a..4bc49aafb 100644 --- a/usrp/host/lib/fusb_libusb1.h +++ b/usrp/host/lib/fusb_libusb1.h @@ -23,7 +23,7 @@ #ifndef _FUSB_LIBUSB1_H_ #define _FUSB_LIBUSB1_H_ -#include +#include #include struct libusb_transfer; diff --git a/usrp/host/lib/fusb_libusb1_base.h b/usrp/host/lib/fusb_libusb1_base.h deleted file mode 100644 index 6a2436453..000000000 --- a/usrp/host/lib/fusb_libusb1_base.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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. - */ - -// Fast USB interface - -#ifndef _FUSB_LIBUSB1_BASE_H_ -#define _FUSB_LIBUSB1_BASE_H_ - -struct libusb_device_handle; -struct libusb_context; -class fusb_ephandle; - -/*! - * \brief abstract usb device handle - */ -class fusb_devhandle { -private: - // NOT IMPLEMENTED - fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor - fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator - -protected: - libusb_device_handle *d_udh; - -public: - // CREATORS - fusb_devhandle (libusb_device_handle *udh); - virtual ~fusb_devhandle (); - - // MANIPULATORS - - /*! - * \brief return an ephandle of the correct subtype - */ - virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0) = 0; - - // ACCESSORS - libusb_device_handle *get_usb_dev_handle () const { return d_udh; } -}; - - -/*! - * \brief abstract usb end point handle - */ -class fusb_ephandle { -private: - // NOT IMPLEMENTED - fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor - fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator - -protected: - int d_endpoint; - bool d_input_p; - int d_block_size; - int d_nblocks; - bool d_started; - -public: - fusb_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0); - virtual ~fusb_ephandle (); - - virtual bool start () = 0; //!< begin streaming i/o - virtual bool stop () = 0; //!< stop streaming i/o - - /*! - * \returns \p nbytes if write was successfully enqueued, else -1. - * Will block if no free buffers available. - */ - virtual int write (const void *buffer, int nbytes) = 0; - - /*! - * \returns number of bytes read or -1 if error. - * number of bytes read will be <= nbytes. - * Will block if no input available. - */ - virtual int read (void *buffer, int nbytes) = 0; - - /* - * block until all outstanding writes have completed - */ - virtual void wait_for_completion () = 0; - - /*! - * \brief returns current block size. - */ - int block_size () { return d_block_size; }; -}; - - -/*! - * \brief factory for creating concrete instances of the appropriate subtype. - */ -class fusb_sysconfig { -public: - /*! - * \brief returns fusb_devhandle or throws if trouble - */ - static fusb_devhandle *make_devhandle (libusb_device_handle *udh, - libusb_context *ctx = 0); - - /*! - * \brief Returns max block size in bytes (hard limit). - */ - static int max_block_size (); - - /*! - * \brief Returns default block size in bytes. - */ - static int default_block_size (); - - /*! - * \brief Returns the default buffer size in bytes. - */ - static int default_buffer_size (); - -}; - -#endif /*_FUSB_LIBUSB1_BASE_H_ */ - diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index ab3c475d5..f71e34fa9 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include +#include #include static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit diff --git a/usrp/host/lib/usrp_basic.h.in b/usrp/host/lib/usrp_basic.h.in new file mode 100644 index 000000000..3faa5304f --- /dev/null +++ b/usrp/host/lib/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/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index 9a1f9fd55..b617f5207 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -25,10 +25,8 @@ #endif #ifdef HAVE_LIBUSB_1 -#include "fusb_libusb1_base.h" #include #else -#include "fusb.h" #include #endif @@ -37,6 +35,7 @@ #include "usrp_interfaces.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" +#include "fusb.h" #include "db_boards.h" #include #include diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc index 7cfd69be6..64cff6078 100644 --- a/usrp/host/lib/usrp_basic_libusb1.cc +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -29,7 +29,7 @@ #include "usrp_interfaces.h" #include "fpga_regs_common.h" #include "fpga_regs_standard.h" -#include "fusb_libusb1_base.h" +#include "fusb.h" #include "db_boards.h" #include #include diff --git a/usrp/host/lib/usrp_prims.h.in b/usrp/host/lib/usrp_prims.h.in new file mode 100644 index 000000000..8198d1797 --- /dev/null +++ b/usrp/host/lib/usrp_prims.h.in @@ -0,0 +1,285 @@ +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. + */ + +void usrp_one_time_init (libusb_context **ctx = NULL); + +/* + * 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); + +/* + * Internal functions + */ + +libusb_device_handle * +usrp_open_interface(libusb_device *dev, int interface, int altinterface); + +int write_cmd (libusb_device_handle *udh, int request, int value, int index, + unsigned char *bytes, int len); + +/* + * Compatibility functions + */ + +libusb_device *_get_usb_device (libusb_device_handle *udh); + +libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); + +int _get_usb_string_descriptor (libusb_device_handle *udh, int index, + unsigned char* data, int length); + +int _usb_control_transfer (libusb_device_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, + unsigned int timeout); + +#endif /* _USRP_PRIMS_H_ */ -- cgit From 889a053c6171a6bc6746aa4e36056a073e8bec4f Mon Sep 17 00:00:00 2001 From: ttsou Date: Tue, 15 Sep 2009 20:28:04 -0400 Subject: Removed internal functions from external header file --- usrp/host/lib/Makefile.am | 8 +++-- usrp/host/lib/usrp_prims_common.cc | 2 +- usrp/host/lib/usrp_prims_libusb0.cc | 2 +- usrp/host/lib/usrp_prims_libusb1.cc | 2 +- usrp/host/lib/usrp_primsi.h | 59 +++++++++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 usrp/host/lib/usrp_primsi.h (limited to 'usrp/host') diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 16f53bd38..4c37a8f15 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -78,7 +78,10 @@ darwin_CODE = \ circular_buffer.h \ circular_linked_list.h \ darwin_libusb.h \ - mld_threads.h + mld_threads.h \ + usrp_prims_libusb0.cc \ + usrp_basic_libusb0.cc + win32_CODE = \ fusb_win32.cc \ @@ -178,7 +181,8 @@ noinst_HEADERS = \ fusb_win32.h \ md5.h \ rate_to_regval.h \ - usrp_config.h + usrp_config.h \ + usrp_primsi.h if PYTHON usrppython_PYTHON = \ diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index 41722b23b..c55098dc3 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -30,7 +30,7 @@ #include #endif -#include "usrp/usrp_prims.h" +#include "usrp_primsi.h" #include "usrp_commands.h" #include "usrp_ids.h" #include "usrp_i2c_addr.h" diff --git a/usrp/host/lib/usrp_prims_libusb0.cc b/usrp/host/lib/usrp_prims_libusb0.cc index 7ff831064..23d278fe8 100644 --- a/usrp/host/lib/usrp_prims_libusb0.cc +++ b/usrp/host/lib/usrp_prims_libusb0.cc @@ -24,7 +24,7 @@ #include "config.h" #endif -#include "usrp/usrp_prims.h" +#include "usrp_primsi.h" #include "usrp_commands.h" #include #include diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index b7eba87ea..0b514e97f 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -24,7 +24,7 @@ #include "config.h" #endif -#include "usrp/usrp_prims.h" +#include "usrp_primsi.h" #include "usrp_commands.h" #include #include diff --git a/usrp/host/lib/usrp_primsi.h b/usrp/host/lib/usrp_primsi.h new file mode 100644 index 000000000..83cc31aee --- /dev/null +++ b/usrp/host/lib/usrp_primsi.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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. + */ + +/* + * Internal usrp_prims header file + */ + +#ifndef _USRP_PRIMSI_H_ +#define _USRP_PRIMSI_H_ + +#include "usrp/usrp_prims.h" + +/* + * Internal functions + */ + +libusb_device_handle * +usrp_open_interface(libusb_device *dev, int interface, int altinterface); + +int write_cmd (libusb_device_handle *udh, int request, int value, int index, + unsigned char *bytes, int len); + +/* + * Compatibility functions + */ + +libusb_device *_get_usb_device (libusb_device_handle *udh); + +libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); + +int _get_usb_string_descriptor (libusb_device_handle *udh, int index, + unsigned char* data, int length); + +int _usb_control_transfer (libusb_device_handle *udh, int request_type, + int request, int value, int index, + unsigned char *data, int length, + unsigned int timeout); + +#endif /* _USRP_PRIMSI_H_ */ + -- cgit From 943a61fcc94d7668c4abf5133806398e8d75148b Mon Sep 17 00:00:00 2001 From: ttsou Date: Wed, 16 Sep 2009 16:39:35 -0400 Subject: Comments for usrp_prims --- usrp/host/lib/usrp_prims.h.in | 46 ++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/usrp_prims.h.in b/usrp/host/lib/usrp_prims.h.in index 8198d1797..dde480b27 100644 --- a/usrp/host/lib/usrp_prims.h.in +++ b/usrp/host/lib/usrp_prims.h.in @@ -5,11 +5,21 @@ 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. + * \brief initialize libusb; Behavior differs depending on libusb version + * + * libusb-0.12 + * + * Probe busses and devices. The argument is ignored and defaults to NULL. + * Safe to call more than once. + * + * libusb-1.0 + * + * If an location to a libusb_context is passed in, create and write in the new + * context. If no argument is provided, initialize libusb with the default + * (NULL) context. + * + * Generally _not_ safe to call more than once with non-NULL argument since a + * new context will be created each time. */ void usrp_one_time_init (libusb_context **ctx = NULL); @@ -256,30 +266,4 @@ bool usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, */ std::string usrp_serial_number(libusb_device_handle *udh); -/* - * Internal functions - */ - -libusb_device_handle * -usrp_open_interface(libusb_device *dev, int interface, int altinterface); - -int write_cmd (libusb_device_handle *udh, int request, int value, int index, - unsigned char *bytes, int len); - -/* - * Compatibility functions - */ - -libusb_device *_get_usb_device (libusb_device_handle *udh); - -libusb_device_descriptor _get_usb_device_descriptor (libusb_device *q); - -int _get_usb_string_descriptor (libusb_device_handle *udh, int index, - unsigned char* data, int length); - -int _usb_control_transfer (libusb_device_handle *udh, int request_type, - int request, int value, int index, - unsigned char *data, int length, - unsigned int timeout); - #endif /* _USRP_PRIMS_H_ */ -- cgit From 8d3550d330eeac88f4991db866288468be084ddf Mon Sep 17 00:00:00 2001 From: ttsou Date: Thu, 17 Sep 2009 11:24:55 -0400 Subject: Allow fusb_sysconfig to build on non-linux libusb-0.12 impls --- usrp/host/lib/fusb_sysconfig_darwin.cc | 2 +- usrp/host/lib/fusb_sysconfig_generic.cc | 2 +- usrp/host/lib/fusb_sysconfig_libusb1.cc | 3 +-- usrp/host/lib/fusb_sysconfig_ra_wb.cc | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/fusb_sysconfig_darwin.cc b/usrp/host/lib/fusb_sysconfig_darwin.cc index 4d19d1292..3d1f656cd 100644 --- a/usrp/host/lib/fusb_sysconfig_darwin.cc +++ b/usrp/host/lib/fusb_sysconfig_darwin.cc @@ -27,7 +27,7 @@ static const int MAX_BLOCK_SIZE = 32 * 1024; // hard limit static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB fusb_devhandle * -fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { return new fusb_devhandle_darwin (udh); } diff --git a/usrp/host/lib/fusb_sysconfig_generic.cc b/usrp/host/lib/fusb_sysconfig_generic.cc index 58baba5a5..271ba6e3a 100644 --- a/usrp/host/lib/fusb_sysconfig_generic.cc +++ b/usrp/host/lib/fusb_sysconfig_generic.cc @@ -27,7 +27,7 @@ static const int MAX_BLOCK_SIZE = 16 * 1024; // hard limit static const int FUSB_BUFFER_SIZE = 2 * (1L << 20); // 2 MB fusb_devhandle * -fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { return new fusb_devhandle_generic (udh); } diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index f71e34fa9..a005f540d 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -30,8 +30,7 @@ static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1 MB struct libusb_context; fusb_devhandle * -fusb_sysconfig::make_devhandle (libusb_device_handle *udh, - libusb_context *ctx) +fusb_sysconfig::make_devhandle (libusb_device_handle *udh, libusb_context *ctx) { return new fusb_devhandle_libusb1 (udh, ctx); } diff --git a/usrp/host/lib/fusb_sysconfig_ra_wb.cc b/usrp/host/lib/fusb_sysconfig_ra_wb.cc index 9da831fd5..561ab2223 100644 --- a/usrp/host/lib/fusb_sysconfig_ra_wb.cc +++ b/usrp/host/lib/fusb_sysconfig_ra_wb.cc @@ -31,7 +31,7 @@ static const int MAX_BLOCK_SIZE = 64 * 1024; static const int FUSB_BUFFER_SIZE = 256 * (1L << 10); // 256 kB fusb_devhandle * -fusb_sysconfig::make_devhandle (usb_dev_handle *udh) +fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { return new fusb_devhandle_ra_wb (udh); } -- cgit From 962a57badaa349da12ca552f4752329aabd4ac6f Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Wed, 23 Sep 2009 17:50:48 -0400 Subject: Change write_internal_ram in usrp_prims to print signed error code --- usrp/host/lib/usrp_prims_common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index c55098dc3..3bdf3a57c 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -221,7 +221,7 @@ write_internal_ram (libusb_device_handle *udh, unsigned char *buf, (unsigned char*)(buf + (addr - start_addr)), n, 1000); if (a < 0){ - fprintf(stderr,"write_internal_ram failed: %u\n", a); + fprintf(stderr,"write_internal_ram failed: %i\n", a); return false; } } -- cgit From df4edacd55663aecee58a9b3f95cbc08bceaab81 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 29 Sep 2009 18:29:44 -0700 Subject: Consolidate conditional headers into libusb_types.h, use automake --- usrp/host/apps/usrper.cc | 7 - usrp/host/include/usrp/.gitignore | 3 + usrp/host/include/usrp/Makefile.am | 4 + usrp/host/include/usrp/libusb_types.h.in | 38 ++ usrp/host/include/usrp/usrp_basic.h | 993 +++++++++++++++++++++++++++++++ usrp/host/include/usrp/usrp_prims.h | 298 ++++++++++ usrp/host/lib/Makefile.am | 33 +- usrp/host/lib/fusb.h | 138 +++++ usrp/host/lib/fusb.h.in | 111 ---- usrp/host/lib/usrp_basic_common.cc | 6 - usrp/host/lib/usrp_prims.h.in | 269 --------- usrp/host/lib/usrp_prims_common.cc | 6 - 12 files changed, 1477 insertions(+), 429 deletions(-) create mode 100644 usrp/host/include/usrp/libusb_types.h.in create mode 100644 usrp/host/include/usrp/usrp_basic.h create mode 100644 usrp/host/include/usrp/usrp_prims.h create mode 100644 usrp/host/lib/fusb.h delete mode 100644 usrp/host/lib/fusb.h.in delete mode 100644 usrp/host/lib/usrp_prims.h.in (limited to 'usrp/host') diff --git a/usrp/host/apps/usrper.cc b/usrp/host/apps/usrper.cc index d1270589b..593cd7921 100644 --- a/usrp/host/apps/usrper.cc +++ b/usrp/host/apps/usrper.cc @@ -33,13 +33,6 @@ #include "usrp/usrp_prims.h" #include "usrp_spi_defs.h" -#include - -#ifdef HAVE_LIBUSB_1 -#include -#else -#include -#endif char *prog_name; diff --git a/usrp/host/include/usrp/.gitignore b/usrp/host/include/usrp/.gitignore index 25b2cae79..0f068a1f3 100644 --- a/usrp/host/include/usrp/.gitignore +++ b/usrp/host/include/usrp/.gitignore @@ -1,3 +1,6 @@ /Makefile /Makefile.in + +# Generated files +/libusb_types.h /usrp_dbid.h diff --git a/usrp/host/include/usrp/Makefile.am b/usrp/host/include/usrp/Makefile.am index d580d8a75..769acc774 100644 --- a/usrp/host/include/usrp/Makefile.am +++ b/usrp/host/include/usrp/Makefile.am @@ -34,6 +34,7 @@ usrpinclude_HEADERS = \ db_tv_rx.h \ db_tv_rx_mimo.h \ db_xcvr2450.h \ + libusb_types.h \ usrp_basic.h \ usrp_bytesex.h \ usrp_dbid.h \ @@ -44,6 +45,9 @@ usrpinclude_HEADERS = \ usrp_subdev_spec.h \ usrp_tune_result.h +EXTRA_DIST = \ + libusb_types.h.in + if PYTHON swiginclude_HEADERS = \ db_base.i diff --git a/usrp/host/include/usrp/libusb_types.h.in b/usrp/host/include/usrp/libusb_types.h.in new file mode 100644 index 000000000..cf10e33cc --- /dev/null +++ b/usrp/host/include/usrp/libusb_types.h.in @@ -0,0 +1,38 @@ +/* -*- Mode: C++ -*- */ +/* + * Copyright 2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _LIBUSB_TYPES_H_ +#define _LIBUSB_TYPES_H_ + +#if @USE_LIBUSB1@ +#include +struct libusb_device; +struct libusb_device_handle; +struct libusb_device_descriptor; +#else +#include +typedef struct usb_device libusb_device; +typedef struct usb_dev_handle libusb_device_handle; +typedef struct usb_device_descriptor libusb_device_descriptor; +#endif + +#endif /* _LIBUSB_TYPES_H_ */ diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h new file mode 100644 index 000000000..063cb3c23 --- /dev/null +++ b/usrp/host/include/usrp/usrp_basic.h @@ -0,0 +1,993 @@ +/* -*- Mode: C++ -*- */ +/* + * Copyright 2005,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _USRP_BASIC_H_ +#define _USRP_BASIC_H_ + +#include +#include +#include +#include +#include +#include +#include + +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 new file mode 100644 index 000000000..042958653 --- /dev/null +++ b/usrp/host/include/usrp/usrp_prims.h @@ -0,0 +1,298 @@ +/* -*- Mode: C++ -*- */ +/* + * Copyright 2005,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _USRP_PRIMS_H_ +#define _USRP_PRIMS_H_ + +#include +#include +#include + +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; Behavior differs depending on libusb version + * + * libusb-0.12 + * + * Probe busses and devices. The argument is ignored and defaults to NULL. + * Safe to call more than once. + * + * libusb-1.0 + * + * If an location to a libusb_context is passed in, create and write in the new + * context. If no argument is provided, initialize libusb with the default + * (NULL) context. + * + * Generally _not_ safe to call more than once with non-NULL argument since a + * new context will be created each time. + */ + +void usrp_one_time_init (libusb_context **ctx = NULL); + +/* + * 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/lib/Makefile.am b/usrp/host/lib/Makefile.am index 4c37a8f15..8a2efa5a8 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -44,19 +44,12 @@ endif EXTRA_DIST = \ std_paths.h.in \ - usrp_dbid.dat \ - fusb.h.in \ - usrp_prims.h.in \ - usrp_basic.h.in + usrp_dbid.dat -BUILT_SOURCES = \ - $(abs_top_builddir)/usrp/host/include/usrp/usrp_dbid.h \ - fusb.h \ - usrp_prims.h \ - usrp_basic.h +BUILT_SOURCES = $(abs_top_builddir)/usrp/host/include/usrp/usrp_dbid.h BUILT_SOURCES += usrp_dbid.cc \ - usrp_dbid.py + usrp_dbid.py # ---------------------------------------------------------------- # FUSB_TECH is set at configure time by way of @@ -200,23 +193,3 @@ gen_sources = $(BUILT_SOURCES) gen_sources_deps = gen_usrp_dbid.py usrp_dbid.dat par_gen_command = PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat include $(top_srcdir)/Makefile.par.gen - - -# Generate libusb dependent header files from configure. -# These are already defined, but override them here, which throws warnings. -# Need to figure out how to separate rules for BUILD_SOURCES. -fusb.h: fusb.h.in $(top_srcdir)/config.status - cd $(top_srcdir) \ - && CONFIG_FILES= CONFIG_HEADERS= CONFIG_OTHER=fusb.h \ - $(SHELL) ./config.status - -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 - diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h new file mode 100644 index 000000000..5e3f3aacb --- /dev/null +++ b/usrp/host/lib/fusb.h @@ -0,0 +1,138 @@ +/* -*- Mode: C++ -*- */ +/* + * Copyright 2005,2009 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _FUSB_H_ +#define _FUSB_H_ + +#include + +struct libusb_context; +class fusb_ephandle; + +/*! + * \brief abstract usb device handle + */ +class fusb_devhandle { +private: + // NOT IMPLEMENTED + fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor + fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator + +protected: + libusb_device_handle *d_udh; + +public: + // CREATORS + fusb_devhandle (libusb_device_handle *udh); + virtual ~fusb_devhandle (); + + // MANIPULATORS + + /*! + * \brief return an ephandle of the correct subtype + */ + virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0) = 0; + + // ACCESSORS + libusb_device_handle *get_usb_dev_handle () const { return d_udh; } +}; + + +/*! + * \brief abstract usb end point handle + */ +class fusb_ephandle { +private: + // NOT IMPLEMENTED + fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor + fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator + +protected: + int d_endpoint; + bool d_input_p; + int d_block_size; + int d_nblocks; + bool d_started; + +public: + fusb_ephandle (int endpoint, bool input_p, + int block_size = 0, int nblocks = 0); + virtual ~fusb_ephandle (); + + virtual bool start () = 0; //!< begin streaming i/o + virtual bool stop () = 0; //!< stop streaming i/o + + /*! + * \returns \p nbytes if write was successfully enqueued, else -1. + * Will block if no free buffers available. + */ + virtual int write (const void *buffer, int nbytes) = 0; + + /*! + * \returns number of bytes read or -1 if error. + * number of bytes read will be <= nbytes. + * Will block if no input available. + */ + virtual int read (void *buffer, int nbytes) = 0; + + /* + * block until all outstanding writes have completed + */ + virtual void wait_for_completion () = 0; + + /*! + * \brief returns current block size. + */ + int block_size () { return d_block_size; }; +}; + + +/*! + * \brief factory for creating concrete instances of the appropriate subtype. + */ +class fusb_sysconfig { +public: + /*! + * \brief returns fusb_devhandle or throws if trouble + */ + static fusb_devhandle *make_devhandle (libusb_device_handle *udh, + libusb_context *ctx = 0); + + /*! + * \brief Returns max block size in bytes (hard limit). + */ + static int max_block_size (); + + /*! + * \brief Returns default block size in bytes. + */ + static int default_block_size (); + + /*! + * \brief Returns the default buffer size in bytes. + */ + static int default_buffer_size (); + +}; + +#endif /* _FUSB_H_ */ diff --git a/usrp/host/lib/fusb.h.in b/usrp/host/lib/fusb.h.in deleted file mode 100644 index 4a65d994f..000000000 --- a/usrp/host/lib/fusb.h.in +++ /dev/null @@ -1,111 +0,0 @@ -struct libusb_context; -class fusb_ephandle; - -/*! - * \brief abstract usb device handle - */ -class fusb_devhandle { -private: - // NOT IMPLEMENTED - fusb_devhandle (const fusb_devhandle &rhs); // no copy constructor - fusb_devhandle &operator= (const fusb_devhandle &rhs); // no assignment operator - -protected: - libusb_device_handle *d_udh; - -public: - // CREATORS - fusb_devhandle (libusb_device_handle *udh); - virtual ~fusb_devhandle (); - - // MANIPULATORS - - /*! - * \brief return an ephandle of the correct subtype - */ - virtual fusb_ephandle *make_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0) = 0; - - // ACCESSORS - libusb_device_handle *get_usb_dev_handle () const { return d_udh; } -}; - - -/*! - * \brief abstract usb end point handle - */ -class fusb_ephandle { -private: - // NOT IMPLEMENTED - fusb_ephandle (const fusb_ephandle &rhs); // no copy constructor - fusb_ephandle &operator= (const fusb_ephandle &rhs); // no assignment operator - -protected: - int d_endpoint; - bool d_input_p; - int d_block_size; - int d_nblocks; - bool d_started; - -public: - fusb_ephandle (int endpoint, bool input_p, - int block_size = 0, int nblocks = 0); - virtual ~fusb_ephandle (); - - virtual bool start () = 0; //!< begin streaming i/o - virtual bool stop () = 0; //!< stop streaming i/o - - /*! - * \returns \p nbytes if write was successfully enqueued, else -1. - * Will block if no free buffers available. - */ - virtual int write (const void *buffer, int nbytes) = 0; - - /*! - * \returns number of bytes read or -1 if error. - * number of bytes read will be <= nbytes. - * Will block if no input available. - */ - virtual int read (void *buffer, int nbytes) = 0; - - /* - * block until all outstanding writes have completed - */ - virtual void wait_for_completion () = 0; - - /*! - * \brief returns current block size. - */ - int block_size () { return d_block_size; }; -}; - - -/*! - * \brief factory for creating concrete instances of the appropriate subtype. - */ -class fusb_sysconfig { -public: - /*! - * \brief returns fusb_devhandle or throws if trouble - */ - static fusb_devhandle *make_devhandle (libusb_device_handle *udh, - libusb_context *ctx = 0); - - /*! - * \brief Returns max block size in bytes (hard limit). - */ - static int max_block_size (); - - /*! - * \brief Returns default block size in bytes. - */ - static int default_block_size (); - - /*! - * \brief Returns the default buffer size in bytes. - */ - static int default_buffer_size (); - -}; - -#endif /* _FUSB_H_ */ diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index b617f5207..91417dbe7 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -24,12 +24,6 @@ #include "config.h" #endif -#ifdef HAVE_LIBUSB_1 -#include -#else -#include -#endif - #include "usrp/usrp_basic.h" #include "usrp/usrp_prims.h" #include "usrp_interfaces.h" diff --git a/usrp/host/lib/usrp_prims.h.in b/usrp/host/lib/usrp_prims.h.in deleted file mode 100644 index dde480b27..000000000 --- a/usrp/host/lib/usrp_prims.h.in +++ /dev/null @@ -1,269 +0,0 @@ -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; Behavior differs depending on libusb version - * - * libusb-0.12 - * - * Probe busses and devices. The argument is ignored and defaults to NULL. - * Safe to call more than once. - * - * libusb-1.0 - * - * If an location to a libusb_context is passed in, create and write in the new - * context. If no argument is provided, initialize libusb with the default - * (NULL) context. - * - * Generally _not_ safe to call more than once with non-NULL argument since a - * new context will be created each time. - */ - -void usrp_one_time_init (libusb_context **ctx = NULL); - -/* - * 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/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index 3bdf3a57c..b687a18e7 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -24,12 +24,6 @@ #include "config.h" #endif -#ifdef HAVE_LIBUSB_1 -#include -#else -#include -#endif - #include "usrp_primsi.h" #include "usrp_commands.h" #include "usrp_ids.h" -- cgit From 152b281b03ab6386938c2cec4394b998c4bb44ef Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 1 Oct 2009 13:33:33 -0400 Subject: Added config.h headers to fix win32 build --- usrp/host/lib/db_base.cc | 4 ++++ usrp/host/lib/db_basic.cc | 4 ++++ usrp/host/lib/db_boards.cc | 4 ++++ usrp/host/lib/db_dbs_rx.cc | 4 ++++ usrp/host/lib/db_dtt754.cc | 4 ++++ usrp/host/lib/db_dtt768.cc | 4 ++++ usrp/host/lib/db_flexrf.cc | 4 ++++ usrp/host/lib/db_tv_rx.cc | 4 ++++ usrp/host/lib/db_xcvr2450.cc | 4 ++++ usrp/host/lib/usrp_standard.cc | 4 ++++ 10 files changed, 40 insertions(+) (limited to 'usrp/host') diff --git a/usrp/host/lib/db_base.cc b/usrp/host/lib/db_base.cc index 102166a86..1cb463429 100644 --- a/usrp/host/lib/db_base.cc +++ b/usrp/host/lib/db_base.cc @@ -19,6 +19,10 @@ // Boston, MA 02110-1301, USA. // +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_basic.cc b/usrp/host/lib/db_basic.cc index 0c6bedec4..1694d6a3f 100644 --- a/usrp/host/lib/db_basic.cc +++ b/usrp/host/lib/db_basic.cc @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_boards.cc b/usrp/host/lib/db_boards.cc index d6c644704..8ef5bac8b 100644 --- a/usrp/host/lib/db_boards.cc +++ b/usrp/host/lib/db_boards.cc @@ -20,6 +20,10 @@ // Boston, MA 02110-1301, USA. // +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/usrp/host/lib/db_dbs_rx.cc b/usrp/host/lib/db_dbs_rx.cc index 99f66c785..98b05d0bf 100644 --- a/usrp/host/lib/db_dbs_rx.cc +++ b/usrp/host/lib/db_dbs_rx.cc @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/usrp/host/lib/db_dtt754.cc b/usrp/host/lib/db_dtt754.cc index d78c5b328..9634c610d 100644 --- a/usrp/host/lib/db_dtt754.cc +++ b/usrp/host/lib/db_dtt754.cc @@ -19,6 +19,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_dtt768.cc b/usrp/host/lib/db_dtt768.cc index a520fdc60..68e307723 100644 --- a/usrp/host/lib/db_dtt768.cc +++ b/usrp/host/lib/db_dtt768.cc @@ -19,6 +19,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_flexrf.cc b/usrp/host/lib/db_flexrf.cc index 2d2bfabbb..f6b44834b 100644 --- a/usrp/host/lib/db_flexrf.cc +++ b/usrp/host/lib/db_flexrf.cc @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_tv_rx.cc b/usrp/host/lib/db_tv_rx.cc index 494ee7a1a..4b28e9bc1 100644 --- a/usrp/host/lib/db_tv_rx.cc +++ b/usrp/host/lib/db_tv_rx.cc @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include diff --git a/usrp/host/lib/db_xcvr2450.cc b/usrp/host/lib/db_xcvr2450.cc index 408a05587..72367286c 100644 --- a/usrp/host/lib/db_xcvr2450.cc +++ b/usrp/host/lib/db_xcvr2450.cc @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/usrp/host/lib/usrp_standard.cc b/usrp/host/lib/usrp_standard.cc index b112dbe0c..541dd3f57 100644 --- a/usrp/host/lib/usrp_standard.cc +++ b/usrp/host/lib/usrp_standard.cc @@ -20,6 +20,10 @@ * Boston, MA 02110-1301, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include "usrp/usrp_prims.h" -- cgit From 6f820db7a8076d38eb2633f44916e2328708ea42 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 1 Oct 2009 12:47:24 -0700 Subject: Add required include directory for new header organization --- usrp/host/lib/Makefile.am | 2 +- usrp/host/swig/Makefile.am | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 8a2efa5a8..17d4b8014 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -20,7 +20,7 @@ include $(top_srcdir)/Makefile.common -common_INCLUDES = $(USRP_INCLUDES) +common_INCLUDES = $(USRP_INCLUDES) -I$(USB_INCLUDEDIR) lib_LTLIBRARIES = libusrp.la diff --git a/usrp/host/swig/Makefile.am b/usrp/host/swig/Makefile.am index 6af452b02..084cc1ba0 100644 --- a/usrp/host/swig/Makefile.am +++ b/usrp/host/swig/Makefile.am @@ -25,6 +25,7 @@ AM_CPPFLAGS = \ $(USRP_INCLUDES) \ $(PYTHON_CPPFLAGS) \ -I$(srcdir) \ + -I$(USB_INCLUDEDIR) \ $(WITH_INCLUDES) ################################# -- cgit From f4a86ccaa23e7e513dbbfa45456ea5783c106ec0 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 1 Oct 2009 13:51:03 -0700 Subject: Cleanup in preparation for merge Fix trailing whitespace Use standard include guards Add more missing config.h includes Fixup emacs mode strings Update copyright notices --- usrp/host/include/usrp/usrp_basic.h | 8 ++-- usrp/host/include/usrp/usrp_prims.h | 14 +++--- usrp/host/lib/db_dbs_rx.cc | 2 +- usrp/host/lib/db_dtt754.cc | 2 +- usrp/host/lib/db_dtt768.cc | 2 +- usrp/host/lib/db_flexrf.cc | 2 +- usrp/host/lib/db_flexrf_mimo.cc | 4 ++ usrp/host/lib/db_tv_rx.cc | 2 +- usrp/host/lib/db_tv_rx_mimo.cc | 6 ++- usrp/host/lib/fusb.cc | 2 +- usrp/host/lib/fusb.h | 2 +- usrp/host/lib/fusb_libusb1.cc | 80 ++++++++++++++++----------------- usrp/host/lib/fusb_libusb1.h | 16 +++---- usrp/host/lib/fusb_sysconfig_darwin.cc | 2 +- usrp/host/lib/fusb_sysconfig_generic.cc | 2 +- usrp/host/lib/fusb_sysconfig_libusb1.cc | 2 +- usrp/host/lib/fusb_sysconfig_linux.cc | 12 ++--- usrp/host/lib/fusb_sysconfig_ra_wb.cc | 2 +- usrp/host/lib/fusb_sysconfig_win32.cc | 2 +- usrp/host/lib/usrp_basic_common.cc | 56 +++++++++++------------ usrp/host/lib/usrp_basic_libusb0.cc | 14 +++--- usrp/host/lib/usrp_basic_libusb1.cc | 14 +++--- usrp/host/lib/usrp_prims_common.cc | 70 ++++++++++++++--------------- usrp/host/lib/usrp_prims_libusb0.cc | 12 ++--- usrp/host/lib/usrp_prims_libusb1.cc | 8 ++-- usrp/host/lib/usrp_primsi.h | 14 +++--- 26 files changed, 180 insertions(+), 172 deletions(-) (limited to 'usrp/host') diff --git a/usrp/host/include/usrp/usrp_basic.h b/usrp/host/include/usrp/usrp_basic.h index 063cb3c23..c24630eb6 100644 --- a/usrp/host/include/usrp/usrp_basic.h +++ b/usrp/host/include/usrp/usrp_basic.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++ -*- */ +/* -*- c++ -*- */ /* * Copyright 2005,2009 Free Software Foundation, Inc. * @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef _USRP_BASIC_H_ -#define _USRP_BASIC_H_ +#ifndef INCLUDED_USRP_BASIC_H +#define INCLUDED_USRP_BASIC_H #include #include @@ -990,4 +990,4 @@ public: bool stop (); }; -#endif +#endif /* INCLUDED_USRP_BASIC_H */ diff --git a/usrp/host/include/usrp/usrp_prims.h b/usrp/host/include/usrp/usrp_prims.h index 042958653..323287d02 100644 --- a/usrp/host/include/usrp/usrp_prims.h +++ b/usrp/host/include/usrp/usrp_prims.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++ -*- */ +/* -*- c++ -*- */ /* * Copyright 2005,2009 Free Software Foundation, Inc. * @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef _USRP_PRIMS_H_ -#define _USRP_PRIMS_H_ +#ifndef INCLUDED_USRP_PRIMS_H +#define INCLUDED_USRP_PRIMS_H #include #include @@ -40,15 +40,15 @@ enum usrp_load_status_t { ULS_ERROR = 0, ULS_OK, ULS_ALREADY_LOADED }; * * Probe busses and devices. The argument is ignored and defaults to NULL. * Safe to call more than once. - * + * * libusb-1.0 * * If an location to a libusb_context is passed in, create and write in the new * context. If no argument is provided, initialize libusb with the default - * (NULL) context. + * (NULL) context. * * Generally _not_ safe to call more than once with non-NULL argument since a - * new context will be created each time. + * new context will be created each time. */ void usrp_one_time_init (libusb_context **ctx = NULL); @@ -295,4 +295,4 @@ bool usrp_write_dboard_offsets (libusb_device_handle *udh, int slot_id, */ std::string usrp_serial_number(libusb_device_handle *udh); -#endif /* _USRP_PRIMS_H_ */ +#endif /* INCLUDED_USRP_PRIMS_H */ diff --git a/usrp/host/lib/db_dbs_rx.cc b/usrp/host/lib/db_dbs_rx.cc index 98b05d0bf..7fe8c4951 100644 --- a/usrp/host/lib/db_dbs_rx.cc +++ b/usrp/host/lib/db_dbs_rx.cc @@ -1,5 +1,5 @@ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // diff --git a/usrp/host/lib/db_dtt754.cc b/usrp/host/lib/db_dtt754.cc index 9634c610d..9ced705e4 100644 --- a/usrp/host/lib/db_dtt754.cc +++ b/usrp/host/lib/db_dtt754.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // diff --git a/usrp/host/lib/db_dtt768.cc b/usrp/host/lib/db_dtt768.cc index 68e307723..0dfe1a8f3 100644 --- a/usrp/host/lib/db_dtt768.cc +++ b/usrp/host/lib/db_dtt768.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // diff --git a/usrp/host/lib/db_flexrf.cc b/usrp/host/lib/db_flexrf.cc index f6b44834b..85ef79bd3 100644 --- a/usrp/host/lib/db_flexrf.cc +++ b/usrp/host/lib/db_flexrf.cc @@ -1,5 +1,5 @@ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // diff --git a/usrp/host/lib/db_flexrf_mimo.cc b/usrp/host/lib/db_flexrf_mimo.cc index e2db5cd10..29bbbd58f 100644 --- a/usrp/host/lib/db_flexrf_mimo.cc +++ b/usrp/host/lib/db_flexrf_mimo.cc @@ -19,6 +19,10 @@ * Boston, MA 02110-1301, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include diff --git a/usrp/host/lib/db_tv_rx.cc b/usrp/host/lib/db_tv_rx.cc index 4b28e9bc1..1822479e1 100644 --- a/usrp/host/lib/db_tv_rx.cc +++ b/usrp/host/lib/db_tv_rx.cc @@ -1,5 +1,5 @@ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // diff --git a/usrp/host/lib/db_tv_rx_mimo.cc b/usrp/host/lib/db_tv_rx_mimo.cc index d0dcb52a9..0964c5d8b 100644 --- a/usrp/host/lib/db_tv_rx_mimo.cc +++ b/usrp/host/lib/db_tv_rx_mimo.cc @@ -1,5 +1,5 @@ // -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008,2009 Free Software Foundation, Inc. // // This file is part of GNU Radio // @@ -18,6 +18,10 @@ // the Free Software Foundation, Inc., 51 Franklin Street, // Boston, MA 02110-1301, USA. +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include db_tv_rx_mimo::db_tv_rx_mimo(usrp_basic_sptr usrp, int which, diff --git a/usrp/host/lib/fusb.cc b/usrp/host/lib/fusb.cc index c14d7c1fb..2a597b67c 100644 --- a/usrp/host/lib/fusb.cc +++ b/usrp/host/lib/fusb.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/fusb.h b/usrp/host/lib/fusb.h index 5e3f3aacb..538ae1ae0 100644 --- a/usrp/host/lib/fusb.h +++ b/usrp/host/lib/fusb.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++ -*- */ +/* -*- c++ -*- */ /* * Copyright 2005,2009 Free Software Foundation, Inc. * diff --git a/usrp/host/lib/fusb_libusb1.cc b/usrp/host/lib/fusb_libusb1.cc index 0171235de..4846f51a5 100644 --- a/usrp/host/lib/fusb_libusb1.cc +++ b/usrp/host/lib/fusb_libusb1.cc @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. - * + * Copyright 2003,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, @@ -35,9 +35,9 @@ #include #include -#define MINIMIZE_TX_BUFFERING true +#define MINIMIZE_TX_BUFFERING true -static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size(); +static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size(); static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE; static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20); // 4 MB endpoint static const int LIBUSB_TIMEOUT = 0; // no timeout @@ -49,7 +49,7 @@ lut_get_ephandle (libusb_transfer *lut) } // ------------------------------------------------------------------------ -// libusb_transfer allocation, deallocation, and callback +// libusb_transfer allocation, deallocation, and callback // ------------------------------------------------------------------------ static void @@ -60,14 +60,14 @@ free_lut (libusb_transfer *lut) if (lut->endpoint & 0x80) delete [] ((unsigned char *) lut->buffer); - libusb_free_transfer(lut); + libusb_free_transfer(lut); } /* * The callback means the libusb_transfer is completed whether sent, cancelled, * or failed. Move the libusb_transfer from the pending list to the - * completed list. If the cancel is from the destructor then free the + * completed list. If the cancel is from the destructor then free the * transfer instead; normally this won't happen since all endpoints should be * destroyed first leaving the pending list empty. */ @@ -77,7 +77,7 @@ generic_callback(struct libusb_transfer *lut) { // Fish out devhandle from endpoint - fusb_devhandle_libusb1* dev_handle = + fusb_devhandle_libusb1* dev_handle = lut_get_ephandle(lut)->get_fusb_devhandle_libusb1(); dev_handle->pending_remove(lut); @@ -87,10 +87,10 @@ generic_callback(struct libusb_transfer *lut) free_lut (lut); return; } - + lut_get_ephandle(lut)->completed_list_add(lut); -} +} static libusb_transfer* alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, @@ -110,11 +110,11 @@ alloc_lut (fusb_ephandle_libusb1 *self, int buffer_length, int endpoint, // Load the libusb_transfer for bulk transfer libusb_fill_bulk_transfer (lut, // transfer - dev_handle, // dev_handle + dev_handle, // dev_handle endpoint, // endpoint write_buffer, // buffer buffer_length, // length - generic_callback, // callback + generic_callback, // callback self, // user_data LIBUSB_TIMEOUT); // timeout @@ -129,7 +129,7 @@ fusb_devhandle_libusb1::fusb_devhandle_libusb1 (libusb_device_handle *udh, libusb_context *ctx) : fusb_devhandle (udh), d_ctx (ctx), d_teardown (false) { - // that's it + // that's it } fusb_devhandle_libusb1::~fusb_devhandle_libusb1 () @@ -160,10 +160,10 @@ fusb_devhandle_libusb1::make_ephandle (int endpoint, bool input_p, } /* - * devhandle list manipulators + * devhandle list manipulators */ -void +void fusb_devhandle_libusb1::pending_add (libusb_transfer *lut) { d_pending_rqsts.push_back (lut); @@ -201,7 +201,7 @@ fusb_devhandle_libusb1::pending_get () } /* - * Match libusb_tranfer with the pending list and erase + * Match libusb_tranfer with the pending list and erase * Return true if found, false otherwise */ @@ -241,11 +241,11 @@ fusb_devhandle_libusb1::_submit_lut (libusb_transfer *lut) } /* - * Attempt to cancel any pending libusb_transfer transactions. + * Attempt to cancel any pending libusb_transfer transactions. * Return true in the absence of errors, which does not mean that the transfer * is cancelled. Cancellation can be checked after the callback is fired off - * by libusb. - */ + * by libusb. + */ bool fusb_devhandle_libusb1::_cancel_lut (libusb_transfer *lut) @@ -287,12 +287,12 @@ fusb_devhandle_libusb1::_reap (bool ok_to_block_p) tv.tv_sec = 0; tv.tv_usec = 0; } - + if ((ret = libusb_handle_events_timeout(d_ctx, &tv)) < 0) { fprintf (stderr, "fusb::_reap libusb_handle_events() %i\n", ret); return false; } - + return true; } @@ -300,9 +300,9 @@ void fusb_devhandle_libusb1::_wait_for_completion () { - while (!d_pending_rqsts.empty ()) - if (!_reap(true)) - break; + while (!d_pending_rqsts.empty ()) + if (!_reap(true)) + break; } @@ -339,7 +339,7 @@ fusb_ephandle_libusb1::fusb_ephandle_libusb1 (fusb_devhandle_libusb1 *dh, fprintf(stderr, "fusb_ephandle_libusb1::ctor: d_block_size = %d d_nblocks = %d\n", d_block_size, d_nblocks); - // allocate libusb_transfers + // allocate libusb_transfers for (int i = 0; i < d_nblocks; i++) d_free_list.push_back (alloc_lut (this, d_block_size, d_endpoint, d_input_p, d_write_buffer, d_devhandle)); @@ -391,7 +391,7 @@ fusb_ephandle_libusb1::start () } /* - * Cancel all transfers in progress or pending and return to initial state + * Cancel all transfers in progress or pending and return to initial state */ bool @@ -434,7 +434,7 @@ fusb_ephandle_libusb1::stop () } // ------------------------------------------------------------------------ -// routines for writing +// routines for writing // ------------------------------------------------------------------------ #if (MINIMIZE_TX_BUFFERING) @@ -444,7 +444,7 @@ fusb_ephandle_libusb1::write (const void *buffer, int nbytes) { if (!d_started) // doesn't matter here, but keeps semantics constant return -1; - + if (d_input_p) return -1; @@ -465,7 +465,7 @@ fusb_ephandle_libusb1::write (const void *buffer, int nbytes) n += m; src += m; - + if (!submit_lut(lut)) return -1; @@ -547,11 +547,11 @@ fusb_ephandle_libusb1::reap_complete_writes () while ((lut = completed_list_get ()) != 0) { // Check for any errors or short writes that were reporetd in the transfer. - // libusb1 sets status, actual_length. + // libusb1 sets status, actual_length. - if (lut->status != LIBUSB_TRANSFER_COMPLETED) { + if (lut->status != LIBUSB_TRANSFER_COMPLETED) { fprintf (stderr, "fusb: (status %d) \n", lut->status ); - } + } else if (lut->actual_length != lut->length){ fprintf (stderr, "fusb: short write xfer: %d != %d\n", lut->actual_length, lut->length); @@ -568,7 +568,7 @@ fusb_ephandle_libusb1::wait_for_completion () } // ------------------------------------------------------------------------ -// routines for reading +// routines for reading // ------------------------------------------------------------------------ int @@ -619,12 +619,12 @@ fusb_ephandle_libusb1::reload_read_buffer () while (1) { - while ((lut = completed_list_get ()) == 0 ) + while ((lut = completed_list_get ()) == 0 ) if (!d_devhandle->_reap(true)) - return false; + return false; if (lut->status != LIBUSB_TRANSFER_COMPLETED) { - fprintf (stderr, "fust: (rd status %d) %s\n", lut->status, + fprintf (stderr, "fust: (rd status %d) %s\n", lut->status, strerror (-lut->status)); lut->actual_length = 0; free_list_add (lut); @@ -641,7 +641,7 @@ fusb_ephandle_libusb1::reload_read_buffer () /* - * ephandle list manipulation + * ephandle list manipulation */ diff --git a/usrp/host/lib/fusb_libusb1.h b/usrp/host/lib/fusb_libusb1.h index 4bc49aafb..c0e3736bd 100644 --- a/usrp/host/lib/fusb_libusb1.h +++ b/usrp/host/lib/fusb_libusb1.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. - * + * Copyright 2003,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, @@ -85,8 +85,8 @@ private: libusb_transfer *get_write_work_in_progress (); void reap_complete_writes (); bool reload_read_buffer (); - bool submit_lut (libusb_transfer *lut); - + bool submit_lut (libusb_transfer *lut); + public: // CREATORS fusb_ephandle_libusb1 (fusb_devhandle_libusb1 *dh, int endpoint, bool input_p, @@ -121,7 +121,7 @@ public: struct libusb_transfer *free_list_get (); struct libusb_transfer *completed_list_get (); - // accessor to work from callback context + // accessor to work from callback context fusb_devhandle_libusb1* get_fusb_devhandle_libusb1 () const { return d_devhandle; } diff --git a/usrp/host/lib/fusb_sysconfig_darwin.cc b/usrp/host/lib/fusb_sysconfig_darwin.cc index 3d1f656cd..68dd64815 100644 --- a/usrp/host/lib/fusb_sysconfig_darwin.cc +++ b/usrp/host/lib/fusb_sysconfig_darwin.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/fusb_sysconfig_generic.cc b/usrp/host/lib/fusb_sysconfig_generic.cc index 271ba6e3a..e0986510c 100644 --- a/usrp/host/lib/fusb_sysconfig_generic.cc +++ b/usrp/host/lib/fusb_sysconfig_generic.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/fusb_sysconfig_libusb1.cc b/usrp/host/lib/fusb_sysconfig_libusb1.cc index a005f540d..46daf561a 100644 --- a/usrp/host/lib/fusb_sysconfig_libusb1.cc +++ b/usrp/host/lib/fusb_sysconfig_libusb1.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/fusb_sysconfig_linux.cc b/usrp/host/lib/fusb_sysconfig_linux.cc index c2e453881..e33b90ba4 100644 --- a/usrp/host/lib/fusb_sysconfig_linux.cc +++ b/usrp/host/lib/fusb_sysconfig_linux.cc @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. - * + * Copyright 2003,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, @@ -30,7 +30,7 @@ static const int FUSB_BUFFER_SIZE = 1 * (1L << 20); // 1MB fusb_devhandle * fusb_sysconfig::make_devhandle (usb_dev_handle *udh, libusb_context *ctx) { - return new fusb_devhandle_linux (udh); + return new fusb_devhandle_linux (udh); } int fusb_sysconfig::max_block_size () diff --git a/usrp/host/lib/fusb_sysconfig_ra_wb.cc b/usrp/host/lib/fusb_sysconfig_ra_wb.cc index 561ab2223..c527e3099 100644 --- a/usrp/host/lib/fusb_sysconfig_ra_wb.cc +++ b/usrp/host/lib/fusb_sysconfig_ra_wb.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2006 Free Software Foundation, Inc. + * Copyright 2003,2006,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/fusb_sysconfig_win32.cc b/usrp/host/lib/fusb_sysconfig_win32.cc index a0d140543..fb4be8829 100644 --- a/usrp/host/lib/fusb_sysconfig_win32.cc +++ b/usrp/host/lib/fusb_sysconfig_win32.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2005 Free Software Foundation, Inc. + * Copyright 2003,2005,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * diff --git a/usrp/host/lib/usrp_basic_common.cc b/usrp/host/lib/usrp_basic_common.cc index 91417dbe7..721301dec 100644 --- a/usrp/host/lib/usrp_basic_common.cc +++ b/usrp/host/lib/usrp_basic_common.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -84,7 +84,7 @@ open_tx_interface (libusb_device *dev) // Given: // CLKIN = 64 MHz -// CLKSEL pin = high +// CLKSEL pin = high // // These settings give us: // CLKOUT1 = CLKIN = 64 MHz @@ -107,8 +107,8 @@ usrp_basic::shutdown_daughterboards() // nuke d'boards before we close down USB in ~usrp_basic // shutdown() will do any board shutdown while the USRP can still // be talked to - for(size_t i = 0; i < d_db.size(); i++) - for(size_t j = 0; j < d_db[i].size(); j++) + for(size_t i = 0; i < d_db.size(); i++) + for(size_t j = 0; j < d_db[i].size(); j++) d_db[i][j]->shutdown(); } @@ -122,7 +122,7 @@ usrp_basic::init_db(usrp_basic_sptr u) d_db[1] = instantiate_dbs(d_dbid[1], u, 1); } -std::vector +std::vector usrp_basic::db(int which_side) { which_side &= 0x1; // clamp it to avoid any reporting any errors @@ -307,7 +307,7 @@ usrp_basic::set_adc_buffer_bypass (int which_adc, bool bypass) bool usrp_basic::set_dc_offset_cl_enable(int bits, int mask) { - return _write_fpga_reg(FR_DC_OFFSET_CL_EN, + return _write_fpga_reg(FR_DC_OFFSET_CL_EN, (d_fpga_shadows[FR_DC_OFFSET_CL_EN] & ~mask) | (bits & mask)); } @@ -399,7 +399,7 @@ usrp_basic::_read_spi (int optional_header, int enables, int format, int len) { if (len <= 0) return ""; - + char buf[len]; if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len)) @@ -741,7 +741,7 @@ usrp_basic_rx::usrp_basic_rx (int which_board, int fusb_block_size, int fusb_nbl if (fusb_nblocks < 0) throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); - + if (fusb_block_size == 0) fusb_block_size = fusb_sysconfig::default_block_size(); @@ -799,7 +799,7 @@ usrp_basic_rx::start () fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n"); return false; } - + return true; } @@ -827,7 +827,7 @@ usrp_basic_rx::make (int which_board, int fusb_block_size, int fusb_nblocks, const std::string firmware_filename) { usrp_basic_rx *u = 0; - + try { u = new usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename); @@ -860,10 +860,10 @@ int usrp_basic_rx::read (void *buf, int len, bool *overrun) { int r; - + if (overrun) *overrun = false; - + if (len < 0 || (len % 512) != 0){ fprintf (stderr, "usrp_basic_rx::read: invalid length = %d\n", len); return -1; @@ -890,7 +890,7 @@ usrp_basic_rx::read (void *buf, int len, bool *overrun) fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n"); } } - + return r; } @@ -940,21 +940,21 @@ usrp_basic_rx::probe_rx_slots (bool verbose) _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_NO_EEPROM: d_dbid[i] = -1; msg = ""; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_INVALID_EEPROM: d_dbid[i] = -2; msg = "Invalid EEPROM contents"; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_BAD_SLOT: default: assert (0); @@ -1144,7 +1144,7 @@ usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nbl if (fusb_nblocks < 0) throw std::out_of_range ("usrp_basic_rx: invalid fusb_nblocks"); - + if (fusb_block_size == 0) fusb_block_size = FUSB_BLOCK_SIZE; @@ -1194,7 +1194,7 @@ usrp_basic_tx::start () fprintf (stderr, "usrp_basic_tx: set_tx_enable failed\n"); return false; } - + if (!d_ephandle->start ()){ fprintf (stderr, "usrp_basic_tx: failed to start end point streaming"); return false; @@ -1227,7 +1227,7 @@ usrp_basic_tx::make (int which_board, int fusb_block_size, int fusb_nblocks, const std::string firmware_filename) { usrp_basic_tx *u = 0; - + try { u = new usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename); @@ -1260,10 +1260,10 @@ int usrp_basic_tx::write (const void *buf, int len, bool *underrun) { int r; - + if (underrun) *underrun = false; - + if (len < 0 || (len % 512) != 0){ fprintf (stderr, "usrp_basic_tx::write: invalid length = %d\n", len); return -1; @@ -1272,7 +1272,7 @@ usrp_basic_tx::write (const void *buf, int len, bool *underrun) r = d_ephandle->write (buf, len); if (r > 0) d_bytes_seen += r; - + /* * In many cases, the FPGA reports an tx underrun right after we * enable the Tx path. If this is our first write, check for the @@ -1347,21 +1347,21 @@ usrp_basic_tx::probe_tx_slots (bool verbose) _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | eeprom.oe); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_NO_EEPROM: d_dbid[i] = -1; msg = ""; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_INVALID_EEPROM: d_dbid[i] = -2; msg = "Invalid EEPROM contents"; _write_fpga_reg (slot_id_to_oe_reg(slot_id), (0xffff << 16) | 0x0000); _write_fpga_reg (slot_id_to_io_reg(slot_id), (0xffff << 16) | 0x0000); break; - + case UDBE_BAD_SLOT: default: assert (0); diff --git a/usrp/host/lib/usrp_basic_libusb0.cc b/usrp/host/lib/usrp_basic_libusb0.cc index 6e41585bb..217480580 100644 --- a/usrp/host/lib/usrp_basic_libusb0.cc +++ b/usrp/host/lib/usrp_basic_libusb0.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -56,7 +56,7 @@ static const double POLLING_INTERVAL = 0.1; // seconds // Given: // CLKIN = 64 MHz -// CLKSEL pin = high +// CLKSEL pin = high // // CLKOUT1 = CLKIN = 64 MHz // CLKOUT2 = CLKIN = 64 MHz @@ -73,7 +73,7 @@ static unsigned char common_regs[] = { }; -usrp_basic::usrp_basic (int which_board, +usrp_basic::usrp_basic (int which_board, struct usb_dev_handle * open_interface (struct usb_device *dev), const std::string fpga_filename, @@ -87,7 +87,7 @@ usrp_basic::usrp_basic (int which_board, * SWAG: Scientific Wild Ass Guess. * * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. - * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the * actual rate. This doesn't change our throughput, that's determined by the signal * processing code in the FPGA (which we know nothing about), and the system limits diff --git a/usrp/host/lib/usrp_basic_libusb1.cc b/usrp/host/lib/usrp_basic_libusb1.cc index 64cff6078..35009dc66 100644 --- a/usrp/host/lib/usrp_basic_libusb1.cc +++ b/usrp/host/lib/usrp_basic_libusb1.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -57,7 +57,7 @@ static const double POLLING_INTERVAL = 0.1; // seconds // Given: // CLKIN = 64 MHz -// CLKSEL pin = high +// CLKSEL pin = high // // These settings give us: // CLKOUT1 = CLKIN = 64 MHz @@ -74,7 +74,7 @@ static unsigned char common_regs[] = { REG_AUX_ADC_CLK, AUX_ADC_CLK_CLK_OVER_4 }; -usrp_basic::usrp_basic (int which_board, +usrp_basic::usrp_basic (int which_board, struct libusb_device_handle * open_interface (struct libusb_device *dev), const std::string fpga_filename, @@ -88,7 +88,7 @@ usrp_basic::usrp_basic (int which_board, * SWAG: Scientific Wild Ass Guess. * * d_usb_data_rate is used only to determine how often to poll for over- and under-runs. - * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., + * We defualt it to 1/2 of our best case. Classes derived from usrp_basic (e.g., * usrp_standard_tx and usrp_standard_rx) call set_usb_data_rate() to tell us the * actual rate. This doesn't change our throughput, that's determined by the signal * processing code in the FPGA (which we know nothing about), and the system limits diff --git a/usrp/host/lib/usrp_prims_common.cc b/usrp/host/lib/usrp_prims_common.cc index b687a18e7..70e90d7fe 100644 --- a/usrp/host/lib/usrp_prims_common.cc +++ b/usrp/host/lib/usrp_prims_common.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -255,7 +255,7 @@ _usrp_load_firmware (libusb_device_handle *udh, const char *filename, if (!reset_cpu (udh, true)) // hold CPU in reset while loading firmware goto fail; - + char s[1024]; int length; int addr; @@ -347,7 +347,7 @@ _usrp_load_fpga (libusb_device_handle *udh, const char *filename, if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_BEGIN, 0, 0) != 0) goto fail; - + while ((n = fread (buf, 1, sizeof (buf), fp)) > 0){ if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_XFER, buf, n) != n) goto fail; @@ -355,7 +355,7 @@ _usrp_load_fpga (libusb_device_handle *udh, const char *filename, if (write_cmd (udh, VRQ_FPGA_LOAD, 0, FL_END, 0, 0) != 0) goto fail; - + fclose (fp); if (!usrp_set_hash (udh, FPGA_HASH_SLOT, hash)) @@ -368,7 +368,7 @@ _usrp_load_fpga (libusb_device_handle *udh, const char *filename, usrp_set_fpga_reset (udh, 0); // fpga out of master reset // now these commands will work - + ok &= usrp_set_fpga_tx_enable (udh, 0); ok &= usrp_set_fpga_rx_enable (udh, 0); @@ -402,7 +402,7 @@ _usrp_load_fpga (libusb_device_handle *udh, const char *filename, // ---------------------------------------------------------------- -bool +bool usrp_set_led (libusb_device_handle *udh, int which, bool on) { int r = write_cmd (udh, VRQ_SET_LED, on, which, 0, 0); @@ -421,7 +421,7 @@ usrp_set_hash (libusb_device_handle *udh, int which, (unsigned char *) hash, USRP_HASH_SIZE, 1000); return r == USRP_HASH_SIZE; } - + bool usrp_get_hash (libusb_device_handle *udh, int which, unsigned char hash[USRP_HASH_SIZE]) @@ -454,7 +454,7 @@ usrp1_fpga_write (libusb_device_handle *udh, buf[1] = (value >> 16) & 0xff; buf[2] = (value >> 8) & 0xff; buf[3] = (value >> 0) & 0xff; - + return usrp_spi_write (udh, 0x00 | (regno & 0x7f), SPI_ENABLE_FPGA, SPI_FMT_MSB | SPI_FMT_HDR_1, @@ -503,31 +503,31 @@ usrp_read_fpga_reg (libusb_device_handle *udh, int reg, int *value) } } -bool +bool usrp_set_fpga_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RESET, on); } -bool +bool usrp_set_fpga_tx_enable (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on); } -bool +bool usrp_set_fpga_rx_enable (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on); } -bool +bool usrp_set_fpga_tx_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_TX_RESET, on); } -bool +bool usrp_set_fpga_rx_reset (libusb_device_handle *udh, bool on) { return usrp_set_switch (udh, VRQ_FPGA_SET_RX_RESET, on); @@ -550,7 +550,7 @@ compute_hash (const char *filename, unsigned char hash[USRP_HASH_SIZE]) } int r = md5_stream (fp, hash); fclose (fp); - + return r == 0; } @@ -565,7 +565,7 @@ usrp_conditionally_load_something (libusb_device_handle *udh, { unsigned char file_hash[USRP_HASH_SIZE]; unsigned char usrp_hash[USRP_HASH_SIZE]; - + if (access (filename, R_OK) != 0){ perror (filename); return ULS_ERROR; @@ -677,13 +677,13 @@ usrp_load_firmware_nth (int nth, const char *filename, bool force, libusb_contex case ULS_OK: // we loaded firmware successfully. - + // It's highly likely that the board will renumerate (simulate a // disconnect/reconnect sequence), invalidating our current // handle. // FIXME. Turn this into a loop that rescans until we refind ourselves - + struct timespec t; // delay for 1 second t.tv_sec = 2; t.tv_nsec = 0; @@ -702,12 +702,12 @@ load_status_msg (usrp_load_status_t s, const char *type, const char *filename) { char *e = getenv("USRP_VERBOSE"); bool verbose = e != 0; - + switch (s){ case ULS_ERROR: fprintf (stderr, "usrp: failed to load %s %s.\n", type, filename); break; - + case ULS_ALREADY_LOADED: if (verbose) fprintf (stderr, "usrp: %s %s already loaded.\n", type, filename); @@ -772,7 +772,7 @@ usrp_load_standard_bits (int nth, bool force, libusb_device_handle *udh = open_nth_cmd_interface (nth, ctx); if (udh == 0) return false; - + s = usrp_load_fpga (udh, filename, force); usrp_close_interface (udh); load_status_msg (s, "fpga bitstream", filename); @@ -789,7 +789,7 @@ _usrp_get_status (libusb_device_handle *udh, int which, bool *trouble) { unsigned char status; *trouble = true; - + if (write_cmd (udh, VRQ_GET_STATUS, 0, which, &status, sizeof (status)) != sizeof (status)) return false; @@ -874,7 +874,7 @@ usrp_9862_write (libusb_device_handle *udh, int which_codec, unsigned char buf[1]; buf[0] = value; - + return usrp_spi_write (udh, 0x00 | (regno & 0x3f), which_codec == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, SPI_FMT_MSB | SPI_FMT_HDR_1, @@ -952,7 +952,7 @@ usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, { unsigned char cmd[2]; const unsigned char *p = (unsigned char *) buf; - + // The simplest thing that could possibly work: // all writes are single byte writes. // @@ -967,7 +967,7 @@ usrp_eeprom_write (libusb_device_handle *udh, int i2c_addr, if (!r) return false; } - + return true; } @@ -994,14 +994,14 @@ usrp_eeprom_read (libusb_device_handle *udh, int i2c_addr, } return true; } - + // ---------------------------------------------------------------- static bool slot_to_codec (int slot, int *which_codec) { *which_codec = 0; - + switch (slot){ case SLOT_TX_A: case SLOT_RX_A: @@ -1038,7 +1038,7 @@ usrp_write_aux_dac (libusb_device_handle *udh, int slot, int which_dac, int value) { int which_codec; - + if (!slot_to_codec (slot, &which_codec)) return false; @@ -1048,7 +1048,7 @@ usrp_write_aux_dac (libusb_device_handle *udh, int slot, } value &= 0x0fff; // mask to 12-bits - + if (which_dac == 3){ // dac 3 is really 12-bits. Use value as is. bool r = true; @@ -1057,7 +1057,7 @@ usrp_write_aux_dac (libusb_device_handle *udh, int slot, return r; } else { - // dac 0, 1, and 2 are really 8 bits. + // dac 0, 1, and 2 are really 8 bits. value = value >> 4; // shift value appropriately return usrp_9862_write (udh, which_codec, 36 + which_dac, value); } @@ -1084,7 +1084,7 @@ usrp_read_aux_adc (libusb_device_handle *udh, int slot, | AUX_ADC_CTRL_REFSEL_B; // on chip reference int rd_reg = 26; // base address of two regs to read for result - + // program the ADC mux bits if (tx_slot_p (slot)) aux_adc_control |= AUX_ADC_CTRL_SELECT_A2 | AUX_ADC_CTRL_SELECT_B2; @@ -1092,7 +1092,7 @@ usrp_read_aux_adc (libusb_device_handle *udh, int slot, rd_reg += 2; aux_adc_control |= AUX_ADC_CTRL_SELECT_A1 | AUX_ADC_CTRL_SELECT_B1; } - + // I'm not sure if we can set the mux and issue a start conversion // in the same cycle, so let's do them one at a time. @@ -1116,7 +1116,7 @@ usrp_read_aux_adc (libusb_device_handle *udh, int slot, if (r) *value = ((v_hi << 2) | ((v_lo >> 6) & 0x3)) << 2; // format as 12-bit - + return r; } diff --git a/usrp/host/lib/usrp_prims_libusb0.cc b/usrp/host/lib/usrp_prims_libusb0.cc index 23d278fe8..7a82eabfa 100644 --- a/usrp/host/lib/usrp_prims_libusb0.cc +++ b/usrp/host/lib/usrp_prims_libusb0.cc @@ -1,19 +1,19 @@ /* -*- 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, @@ -109,7 +109,7 @@ usrp_find_device (int nth, bool fx2_ok_p, libusb_context *ctx) int n_found = 0; usrp_one_time_init (); - + p = usb_get_busses(); while (p != NULL){ q = p->devices; @@ -147,7 +147,7 @@ usrp_open_interface (struct usb_device *dev, int interface, int altinterface) // Appears to be required for libusb-win32 and Cygwin -- dew 09/20/06 if (usb_set_configuration (udh, 1) < 0){ /* - * Ignore this error. + * Ignore this error. * * Seems that something changed in drivers/usb/core/devio.c:proc_setconfig such that * it returns -EBUSY if _any_ of the interfaces of a device are open. diff --git a/usrp/host/lib/usrp_prims_libusb1.cc b/usrp/host/lib/usrp_prims_libusb1.cc index 0b514e97f..cf1f8fe07 100644 --- a/usrp/host/lib/usrp_prims_libusb1.cc +++ b/usrp/host/lib/usrp_prims_libusb1.cc @@ -1,19 +1,19 @@ /* -*- 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, diff --git a/usrp/host/lib/usrp_primsi.h b/usrp/host/lib/usrp_primsi.h index 83cc31aee..b1cf7263a 100644 --- a/usrp/host/lib/usrp_primsi.h +++ b/usrp/host/lib/usrp_primsi.h @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. - * + * Copyright 2003,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, @@ -30,7 +30,7 @@ #include "usrp/usrp_prims.h" /* - * Internal functions + * Internal functions */ libusb_device_handle * @@ -40,7 +40,7 @@ int write_cmd (libusb_device_handle *udh, int request, int value, int index, unsigned char *bytes, int len); /* - * Compatibility functions + * Compatibility functions */ libusb_device *_get_usb_device (libusb_device_handle *udh); -- cgit From d894a95ef6370f91ec14334e6b2b2f578a1cb090 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Fri, 2 Oct 2009 21:46:41 -0400 Subject: usrp: Build fix for non-pkgconfig installs of libusb --- usrp/host/lib/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'usrp/host') diff --git a/usrp/host/lib/Makefile.am b/usrp/host/lib/Makefile.am index 17d4b8014..2f8cbe6de 100644 --- a/usrp/host/lib/Makefile.am +++ b/usrp/host/lib/Makefile.am @@ -20,7 +20,7 @@ include $(top_srcdir)/Makefile.common -common_INCLUDES = $(USRP_INCLUDES) -I$(USB_INCLUDEDIR) +common_INCLUDES = $(USRP_INCLUDES) $(USB_INCLUDES) lib_LTLIBRARIES = libusrp.la -- cgit From 0aba348525787c7deb3255e87e17187f6cc6f218 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Sat, 3 Oct 2009 12:59:34 -0700 Subject: Fix missing update from last commit --- usrp/host/swig/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'usrp/host') diff --git a/usrp/host/swig/Makefile.am b/usrp/host/swig/Makefile.am index 084cc1ba0..d2e6b8bc1 100644 --- a/usrp/host/swig/Makefile.am +++ b/usrp/host/swig/Makefile.am @@ -25,7 +25,7 @@ AM_CPPFLAGS = \ $(USRP_INCLUDES) \ $(PYTHON_CPPFLAGS) \ -I$(srcdir) \ - -I$(USB_INCLUDEDIR) \ + $(USB_INCLUDES) \ $(WITH_INCLUDES) ################################# -- cgit