* Copyright 2003,2006,2007,2008 Free Software Foundation, Inc.
* any later version.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* along with GNU Radio; see the file COPYING. If not, write to
* Boston, MA 02110-1301, USA.
usrp_standard_rx *urx = usrp_standard_rx::make (which_board, decim, 1, -1, mode, fusb_block_size, fusb_nblocks);
#include "usb.h"
#include "usrp_spi_defs.h"
#include "usrp_commands.h"
#include "fpga_regs_standard.h"
#include "ad9862.h"
#include <stdio.h>
#include <math.h>
int d_first_read = 1;
/* the device's vendor and product id */
#define MY_VID 0xFFFE
#define MY_PID 0x0002
/* the device's endpoints */
#define EP_IN 6
#define EP_OUT 0x01
#define SAMPELS_PER_READ (512) // Must be a multiple of 128
#define USB_TIMEOUT (1000)
#define BUF_SIZE 64
#define MAX_CHAN 4
#define MAX_REGS 128
#define MAX_EP0_PKTSIZE 64
#define VRT_VENDOR_IN 0xC0
#define VRT_VENDOR_OUT 0x40
#define REG_RX_A 2 // bypass input buffer / RxPGA
#define REG_RX_B 3
const double POLLING_INTERVAL = 0.1;
double d_rx_freq[MAX_CHAN];
unsigned int d_fpga_shadows[MAX_REGS];
int d_verbose = 0;
struct usb_dev_handle *d_udh;
usb_dev_handle *udh;
int d_fpga_caps;
int d_nchan;
int d_tx_enable;
int d_hw_mux;
int d_sw_mux;
unsigned int d_decim_rate;
int d_usb_data_rate = 16000000;
int d_bytes_per_poll;
int d_rx_enable;
struct usb_device *myDev;
usb_dev_handle *open_dev(void);
unsigned int compute_freq_control_word_fpga(double, double, double *, int);
int _write_fpga_reg (int regno, int value);
int set_rx_freq (int , double);
usb_dev_handle *open_dev(void)
{
struct usb_bus *bus;
struct usb_device *dev;
for(bus = usb_get_busses(); bus; bus = bus->next)
{
for(dev = bus->devices; dev; dev = dev->next)
{
if(dev->descriptor.idVendor == MY_VID
&& dev->descriptor.idProduct == MY_PID)
{
myDev = dev;
return usb_open(dev);
}
}
}
return NULL;
}
double rint(double x)
{
//middle value point test
if (ceil(x+0.5) == floor(x+0.5))
{
int a = (int)ceil(x);
if (a%2 == 0)
{
return ceil(x);
}
else
{
return floor(x);
}
}
else return floor(x+0.5);
}
static unsigned int compute_freq_control_word_fpga(double master_freq, double target_freq, double *actual_freq, int verbose)
{
static const int NBITS = 14;
int v = rint (target_freq / master_freq * pow (2.0, 32.0));
if (0)
v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS
*actual_freq = v * master_freq / pow (2.0, 32.0);
if (verbose)
fprintf (stderr,"compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n",target_freq, *actual_freq, *actual_freq - target_freq);
return (unsigned int) v;
}
int usrp_hw_rev (struct usb_device *q)
{
return q->descriptor.bcdDevice & 0x00FF;
}
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 *) d_udh)->device;
return myDev;
}
static 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;
}
int usrp_spi_write (struct usb_dev_handle *udh,
int optional_header, int enables, int format,
const void *buf, int len)
{
if (len < 0 || len > MAX_EP0_PKTSIZE)
return 0;
return write_cmd (udh, VRQ_SPI_WRITE,
optional_header,
((enables & 0xff) << 8) | (format & 0xff),
(unsigned char *) buf, len) == len;
}
static int usrp1_fpga_write (struct usb_dev_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));
}
int usrp_write_fpga_reg (struct usb_dev_handle *udh, int reg, int value)
{
switch (usrp_hw_rev (dev_handle_to_dev (udh))){
case 0: // not supported ;)
abort();
default:
return usrp1_fpga_write (udh, reg, value);
}
}
int _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);
}
long fpga_master_clock_freq ()
{
return 64000000;
}
long converter_rate()
{
return fpga_master_clock_freq();
}
long adc_rate() { return converter_rate(); }
int set_rx_freq (int channel, double freq)
{
unsigned int v;
if (channel < 0 || channel > MAX_CHAN)
return 0;
v = compute_freq_control_word_fpga (adc_rate(),freq, &d_rx_freq[channel], d_verbose);
return _write_fpga_reg (FR_RX_FREQ_0 + channel, v);
}
// ------------------------------------------------------------------------------------------------------------------------------
int tx_enable () { return d_tx_enable; }
static int usrp_set_switch (struct usb_dev_handle *udh, int cmd_byte, int on)
{
return write_cmd (udh, cmd_byte, on, 0, 0, 0) == 0;
}
int usrp_set_fpga_tx_enable (struct usb_dev_handle *udh, int on)
{
return usrp_set_switch (udh, VRQ_FPGA_SET_TX_ENABLE, on);
}
int set_tx_enable (int on)
{
d_tx_enable = on;
// fprintf (stderr, "set_tx_enable %d\n", on);
return usrp_set_fpga_tx_enable (d_udh, on);
}
int disable_tx ()
{
int enabled = tx_enable ();
if (enabled)
set_tx_enable (0);
return enabled;
}
void restore_tx (int on)
{
if (on != tx_enable ())
set_tx_enable (on);
}
int write_hw_mux_reg ()
{
int s = disable_tx ();
int ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan);
restore_tx (s);
return ok;
}
int nddcs()
{
return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT;
}
int set_nchannels (int nchan)
{
if (!(nchan == 1 || nchan == 2 || nchan == 4))
return 0;
if (nchan > nddcs())
return 0;
d_nchan = nchan;
return write_hw_mux_reg ();
}
//--------------------------------------------------------------------------------------------------------------------------------
int usrp_spi_read (struct usb_dev_handle *udh,
int optional_header, int enables, int format,
void *buf, int len)
{
if (len < 0 || len > MAX_EP0_PKTSIZE)
return 0;
return write_cmd (udh, VRQ_SPI_READ,
optional_header,
((enables & 0xff) << 8) | (format & 0xff),
(unsigned char *) buf, len) == len;
}
int usrp_9862_read (struct usb_dev_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);
}
const int _read_9862 (int which_codec, int regno, unsigned char *value)
{
return usrp_9862_read (d_udh, which_codec, regno, value);
}
int usrp_9862_write (struct usb_dev_handle *udh, int which_codec, int regno, int value)
{
unsigned char buf[1];
if (0)
fprintf (stderr, "usrp_9862_write which = %d, reg = %2d, val = %3d (0x%02x)\n",which_codec, regno, value, value);
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);
}
int _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);
}
double pga_min () { return 0.0; }
double pga_db_per_step () { return 20.0 / 20; }
int set_pga (int which, double gain)
{
int codec;
int reg;
char cur_rx;
int int_gain;
if (which < 0 || which > 3)
return 0;
//gain = std::max (pga_min (), gain);
//gain = std::min (pga_max (), gain);
codec = which >> 1;
reg = (which & 1) == 0 ? REG_RX_A : REG_RX_B;
// read current value to get input buffer bypass flag.
//unsigned
if (!_read_9862 (codec, reg, &cur_rx))
return 0;
int_gain = (int) rint ((gain - pga_min ()) / pga_db_per_step());
cur_rx = (cur_rx & RX_X_BYPASS_INPUT_BUFFER) | (int_gain & 0x7f);
return _write_9862 (codec, reg, cur_rx);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr)
{
// confirm that all I's are either 0,1,2,3
int i;
int q_and ;
int q_or ;
for ( i = 0; i < 8; i += 2){
int t = (sw_mux >> (4 * i)) & 0xf;
if (!(0 <= t && t <= 3))
return 0;
}
// confirm that all Q's are either 0,1,2,3 or 0xf
for ( i = 1; i < 8; i += 2){
int t = (sw_mux >> (4 * i)) & 0xf;
if (!(t == 0xf || (0 <= t && t <= 3)))
return 0;
}
// confirm that all Q inputs are 0xf (const zero input),
// or none of them are 0xf
q_and = 1;
q_or = 0;
for ( i = 0; i < 4; i++){
int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf;
q_and &= qx_is_0xf;
q_or |= qx_is_0xf;
}
if (q_and || !q_or){ // OK
int hw_mux_value = 0;
for (i = 0; i < 8; i++){
int t = (sw_mux >> (4 * i)) & 0x3;
hw_mux_value |= t << (2 * i + 4);
}
if (q_and)
hw_mux_value |= 0x8; // all Q's zero
*hw_mux_ptr = hw_mux_value;
return 1;
}
else
return 0;
}
int set_mux (int mux)
{
if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux))
return 0;
// fprintf (stderr, "sw_mux = 0x%08x hw_mux = 0x%08x\n", mux, d_hw_mux);
d_sw_mux = mux;
return write_hw_mux_reg ();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int rx_enable () { return d_rx_enable; }
int usrp_set_fpga_rx_enable (struct usb_dev_handle *udh, int on)
{
return usrp_set_switch (udh, VRQ_FPGA_SET_RX_ENABLE, on);
}
int set_rx_enable (int on)
{
d_rx_enable = on;
return usrp_set_fpga_rx_enable (d_udh, on);
}
int has_rx_halfband()
{
return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? 1 : 0;
}
void 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);
}
int nchannels () { return d_nchan; }
int disable_rx ()
{
int enabled = rx_enable ();
if (enabled)
set_rx_enable (0);
return enabled;
}
void restore_rx (int on)
{
if (on != rx_enable ())
set_rx_enable (on);
}
int set_decim_rate(unsigned int rate)
{
int s;
int v;
int ok;
if (has_rx_halfband()){
if ((rate & 0x1) || rate < 4 || rate > 256){
fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n");
return 0;
}
}
else {
if (rate < 4 || rate > 128){
fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be in [4, 128]\n");
return 0;
}
}
d_decim_rate = rate;
set_usb_data_rate ((adc_rate () / rate * nchannels ())
* (2 * sizeof (short)));
s = disable_rx ();
v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1;
ok = _write_fpga_reg (FR_DECIM_RATE, v);
restore_rx (s);
return ok;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int set_ddc_phase(int channel, int phase)
{
if (channel < 0 || channel >= MAX_CHAN)
return 0;
return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int start ()
{
if (!start ())
return 0;
// add our code here
return 1;
}
int stop (){
int ok ;
ok= stop (); // add our code here
return ok;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int fusb_generic_read (void *buffer, int nbytes)
{
/*if (!d_started) // doesn't matter here, but keeps semantics constant
return -1;
if (!d_input_p)
return -1;
*/
if(usb_bulk_read(d_udh,0|EP_IN, (char *) buffer, nbytes,
USB_TIMEOUT))
{
printf("error: bulk read failed\n");
}
else
if(usb_bulk_read(d_udh, EP_IN, (char *) buffer, nbytes, USB_TIMEOUT)
{
printf("error: bulk read failed\n");
return;
}
else
return usb_bulk_read (d_udh, EP_IN, (char *) buffer, nbytes,
USB_TIMEOUT);
}
int read (void *buf, int len, int *overrun)
{
int r;
int bogus_overrun;
int d_bytes_seen = 0;
if (overrun)
*overrun = 0;
if (len < 0 || (len % 512) != 0){
fprintf (stderr, "read: invalid length = %d\n", len);
return -1;
}
r = fusb_generic_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 = 0;
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");
usb_strerror ();
}
}
*/
return r;
}
int main(void)
{
usb_dev_handle *udh; /* the device handle */
char tmp[BUF_SIZE];
int a;
int noverruns = 0;
int overrun;
int total_reads = 10000;
int i;
int buf[SAMPELS_PER_READ];
int bufsize = sizeof(buf);
char * tempBuf[4*SAMPELS_PER_READ];
udh = d_udh;
usb_init(); /* initialize the library */
usb_find_busses(); /* find all busses */
usb_find_devices(); /* find all connected devices */
if(!(d_udh = open_dev()))
{
printf("error: device not found!\n");
return 0;
}
if(usb_set_configuration(d_udh, 1) < 0)
{
printf("error: setting config 1 failed\n");
usb_close(d_udh);
return 0;
}
if(usb_claim_interface(d_udh, 0) < 0)
{
printf("error: claiming interface 0 failed\n");
usb_close(d_udh);
return 0;
}
set_rx_freq (0,0);
set_nchannels (1);
set_pga (0, 0);
set_mux(0x32103210); // Board A only
set_decim_rate(8);
set_ddc_phase(0,0);
printf("USRP Transfer Starts\n");
// Do USRP Samples Reading
for (i = 0; i < 6; i++)
{
read(&buf, bufsize, &overrun);
if (overrun)
{
printf ("USRP Rx Overrun\n");
noverruns++;
}
// Do whatever you want with the data
}
printf("USRP Transfer Stopped\n");
usb_release_interface(d_udh, 0);
usb_close(d_udh);
return 0;
}
However, bulk read fails with this code. Please can you tell me where I am going wrong?