USB Bulk Read Fails


#1

Hi,
I am trying to take samples from USRP in a C program. What I have done
in
order to perform this task is that I have manually taken out all the
functions from all the USRP cc and header files which will be used. I
have
followed the following code which is already available for Linux:

// Simple C++ USRP interfacing demonstration program
//
//
// This program was derived and modified from test_usrp_standard_rx.cc
/* -- c++ -- /
/

  • Copyright 2003,2006,2007,2008 Free Software Foundation, Inc.
  • This file is part of GNU Radio

Page 53 of 90

  • 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 “usrp_standard.h”
    // Dumy Function to process USRP data
    void process_data(int buffer)
    {
    }
    #define SAMPELS_PER_READ (512) // Must be a multiple of 128
    int main (int argc, char **argv)
    {
    bool loopback_p = false;
    bool counting_p = false;
    bool width_8_p = false;
    int which_board = 0;
    int decim = 8; // 32 MB/sec
    double center_freq = 0;
    int fusb_block_size = 0;
    int fusb_nblocks = 0;
    int nchannels = 1;
    int gain = 0;
    int mode = 0;
    int noverruns = 0;
    bool overrun;
    int total_reads = 10000;
    int i;
    int buf[SAMPELS_PER_READ];
    int bufsize = SAMPELS_PER_READ
    4;

if (loopback_p) mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK;

if (counting_p) mode |= usrp_standard_rx::FPGA_MODE_COUNTING;

usrp_standard_rx *urx = usrp_standard_rx::make (which_board, decim, 1,
-1,
mode, fusb_block_size, fusb_nblocks);

if (urx == 0)
{
fprintf (stderr, “Error: usrp_standard_rx::make\n”);
exit (1);
}

if (width_8_p)
{
int width = 8;
int shift = 8;
bool want_q = true;
if (!urx->set_format(usrp_standard_rx::make_format(width, shift,
want_q)))
{
fprintf (stderr, “Error: urx->set_format\n”);
exit (1);
}
}
// Set DDC center frequency
urx->set_rx_freq (0, center_freq);
// Set Number of channels
urx->set_nchannels(1);
// Set ADC PGA gain
urx->set_pga(0,gain);
// Set FPGA Mux
urx->set_mux(0x32103210); // Board A only
// Set DDC decimation rate
urx->set_decim_rate(decim);
// Set DDC phase
urx->set_ddc_phase(0,0);

urx->start(); // Start data transfer

printf(“USRP Transfer Started\n”);
// Do USRP Samples Reading
for (i = 0; i < total_reads; i++)
{
urx->read(&buf, bufsize, &overrun);
if (overrun)
{
printf (“USRP Rx Overrun\n”);
noverruns++;
}
// Do whatever you want with the data
process_data(&buf[0]);
}

urx->stop(); // Stop data transfer
printf(“USRP Transfer Stoped\n”);

delete urx;
return 0;
}

This is my own code written for Windows based on the above code:

#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 :wink:
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?