/* -*- 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,
#include "config.h"
#endif
-#include <usrp/usrp_basic.h>
+#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 <libusb-1.0/libusb.h>
#include <stdexcept>
#include <assert.h>
#include <math.h>
////////////////////////////////////////////////////////////////
-static struct libusb_device_handle *
-open_rx_interface (struct libusb_device *dev)
+static libusb_device_handle *
+open_rx_interface (libusb_device *dev)
{
- struct libusb_device_handle *udh = usrp_open_rx_interface (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 struct libusb_device_handle *
-open_tx_interface (struct libusb_device *dev)
+static libusb_device_handle *
+open_tx_interface (libusb_device *dev)
{
- struct libusb_device_handle *udh = usrp_open_tx_interface (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
+// CLKSEL pin = high
//
// These settings give us:
// CLKOUT1 = CLKIN = 64 MHz
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),
+usrp_basic::usrp_basic (int which_board,
+ libusb_device_handle *
+ open_interface (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)
/*
* 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.
+ * 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 ();
+ usrp_one_time_init (&d_ctx);
- 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);
+ 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");
// initialize registers that are common to rx and tx
- if (!usrp_9862_write_many_all (d_udh, common_regs, sizeof (common_regs))){
+ 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);
+ usrp_close_interface (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.
+ usrp_deinit (d_ctx);
+}
- //libusb_exit (NULL);
+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
d_db[1] = instantiate_dbs(d_dbid[1], u, 1);
}
-std::vector<db_base_sptr>
+std::vector<db_base_sptr>
usrp_basic::db(int which_side)
{
which_side &= 0x1; // clamp it to avoid any reporting any errors
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));
}
{
if (len <= 0)
return "";
-
+
char buf[len];
if (!usrp_spi_read (d_udh, optional_header, enables, format, buf, len))
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_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx);
d_ephandle = d_devhandle->make_ephandle (USRP_RX_ENDPOINT, true,
fusb_block_size, fusb_nblocks);
fprintf (stderr, "usrp_basic_rx: set_rx_enable failed\n");
return false;
}
-
+
return true;
}
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);
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;
fprintf (stderr, "usrp_basic_rx: usrp_check_rx_overrun failed\n");
}
}
-
+
return r;
}
_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 = "<none>";
_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 (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_devhandle = fusb_sysconfig::make_devhandle (d_udh, d_ctx);
d_ephandle = d_devhandle->make_ephandle (USRP_TX_ENDPOINT, false,
fusb_block_size, fusb_nblocks);
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;
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);
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
_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 = "<none>";
_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);