mirror of https://gerrit.osmocom.org/libusrp
146 lines
4.4 KiB
C++
146 lines
4.4 KiB
C++
/* -*- 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 <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>
|
|
#include <ad9862.h>
|
|
#include <string.h>
|
|
#include <cstdio>
|
|
|
|
|
|
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
|
|
//
|
|
// 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));
|
|
|
|
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");
|
|
|
|
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 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);
|
|
}
|
|
|