Transmitting from file stored by usrp_rx_cfile.py


#1

I am trying to transmit from a file stored using usrp_rx_cfile.py (or
usrp_rx_cfile created using usrp_rx_cfile.cc/h). I have been able to
successfully do this using a usrp_tx_cfile.cc/h program derived from the
rx
version. I can’t, however, get similar functionality using python. I
am
new to python, so I am hoping I have just missed some key insight. I
have
listed below the source for my cc and py versions of usrp_tx_cfile and
the
associated command line output from the transmit side. I am running on
Mac
OS X with gnuradio code pulled down on Feb 13, 2009. My daughterboards
are
RFX2400 and I am receiving on two other machines with the same USRP set
up,
but different hardware and OS (Linux). I am using usrp_fft and
usrp_oscope
on the receiving side. To test functionality, I stored data on the Mac
using usrp_rx_cfile while running “usrp_siggen -f 2500000000” on one of
the
other machines.

Also, I noticed that when I use the subdev->gain_min() and
subdev->gain_max() functions, both return 0 instead of correct values.

C++ code is shown below first, followed by the non-working python code.
Any
help is much appreciated!
-Jaze

So, when I compile and run this code, I see the waveform on the
receiver:

/*

  • usrp_tx_cfile.cc - code based on usrp_rx_cfile.cc
    */

#include <usrp_tx_cfile.h>
#include <gr_io_signature.h>
#include <gr_head.h>
#include
#include
#include <boost/program_options.hpp>

namespace po = boost::program_options;

usrp_subdev_spec
str_to_subdev(std::string spec_str)
{
usrp_subdev_spec spec;
if(spec_str == “A” || spec_str == “A:0” || spec_str == “0:0”) {
spec.side = 0;
spec.subdev = 0;
}
else if(spec_str == “A:1” || spec_str == “0:1”) {
spec.side = 0;
spec.subdev = 1;
}
else if(spec_str == “B” || spec_str == “B:0” || spec_str == “1:0”) {
spec.side = 1;
spec.subdev = 0;
}
else if(spec_str == “B:1” || spec_str == “1:1”) {
spec.side = 1;
spec.subdev = 1;
}
else {
throw std::range_error(“Incorrect subdevice specifications.\n”);
}

return spec;
}

// Shared pointer constructor
usrp_tx_cfile_sptr make_usrp_tx_cfile(int which, usrp_subdev_spec spec,
int interp, double freq, float gain,
bool width8, bool nohb,
bool output_shorts, int nsamples,
const std::string &filename)
{
return gnuradio::get_initial_sptr(new usrp_tx_cfile(which, spec,
interp, freq, gain,
width8, nohb,
output_shorts,
nsamples,
filename));
}

// Hierarchical block constructor, with no inputs or outputs
usrp_tx_cfile::usrp_tx_cfile(int which, usrp_subdev_spec spec,
int interp, double freq, float gain,
bool width8, bool nohb,
bool output_shorts, int nsamples,
const std::string &filename) :
gr_top_block(“usrp_tx_cfile”),
d_which(which), d_spec(spec), d_interp(interp), d_freq(freq),
d_gain(gain), d_width8(width8), d_nohb(nohb), d_nsamples(nsamples),
d_filename(filename)
{
usrp_sink_c_sptr usrp = usrp_make_sink_c(d_which, d_interp);

// standard fpga firmware “std_2rxhb_2tx.rbf” contains
// 2 Rx paths with halfband filters and 2 tx paths
//(the default) min decimation 8
//usrp = usrp_make_source_c(d_which, d_decim);

/* Get subdevice and process it */
db_base_sptr subdev = usrp->selected_subdev(d_spec);
printf("\nSubdevice name is %s\n", subdev->side_and_name().c_str());
printf(“Subdevice freq range: (%g, %g)\n”,
subdev->freq_min(), subdev->freq_max());

unsigned int mux = usrp->determine_tx_mux_value(d_spec);
printf(“mux: %#08x\n”, mux);
usrp->set_mux(mux);

float gain_min = subdev->gain_min();
float gain_max = subdev->gain_max();
printf (“gain min is %g. gain max is %g.\n”, gain_min, gain_max);
if(d_gain == -1) {
//d_gain = (gain_min + gain_max)/2.0;
printf(“No gain specified. Setting to max gain.\n”);
d_gain = gain_max;
d_gain = 90;
}
printf(“gain: %g\n”, d_gain);
subdev->set_gain(d_gain);

float input_rate = usrp->dac_freq() / usrp->interp_rate();
printf(“baseband rate: %g\n”, input_rate);

/* Set the USRP/dboard frequency */
usrp_tune_result r;
//bool ok = usrp->tune(0, subdev, freq, &r); //DDC 0
bool ok = usrp->tune(subdev->which(), subdev, d_freq, &r);

if(!ok) {
throw std::runtime_error(“Could not set frequency.”);
}

subdev->set_enable(true);

/* The rest */
d_src = gr_make_file_source(sizeof(gr_complex), d_filename.c_str());

//if(d_nsamples == -1) {
connect(d_src, 0, usrp, 0);
//}
//else {
// d_head = gr_make_head(sizeof(gr_complex), d_nsamples*2);
// connect(usrp, 0, d_head, 0);
// connect(d_head, 0, d_dst, 0);
//}
}

int main(int argc, char *argv[])
{
int which = 0; // specify which USRP board
usrp_subdev_spec spec(0,0); // specify the d’board side
int interp = 128; // set the decimation rate
double freq = 0; // set the frequency
float gain = -1; // set the gain; -1 will set the
mid-point gain
int nsamples = -1; // set the number of samples to
collect; -1 will continue
bool width8 = false; // use 8-bit samples across USB
bool nohb = false; // don’t use halfband filter in
USRP
bool output_shorts = false; // use shorts
std::string filename = “received.dat”;

po::options_description cmdconfig(“Program options: usrp_tx_cfile
[options] filename”);
cmdconfig.add_options()
(“help,h”, “produce help message”)
(“which,W”, po::value(&which), “select which USRP board”)
(“rx-subdev-spec,R”, po::valuestd::string(), “select USRP Rx side
A or
B (default=A)”)
(“interp,i”, po::value(&interp), “set fgpa interpolation rate
to
INTERP”)
(“freq,f”, po::value(), “set frequency to FREQ”)
(“gain,g”, po::value(), “set gain in dB (default is
midpoint)”)
(“width-8,8”, “Enable 8-bit samples across USB”)
(“no-hb”, “don’t use halfband filter in usrp”)
//(“output-shorts,s”, “output interleaved shorts in stead of complex
floats”)
//(“nsamples,N”, po::value(&nsamples), “number of samples to
collect”)
;

po::options_description fileconfig(“Input file options”);
fileconfig.add_options()
(“filename”, po::valuestd::string(), “input file”)
;

po::positional_options_description inputfile;
inputfile.add(“filename”, -1);

po::options_description config;
config.add(cmdconfig).add(fileconfig);

po::variables_map vm;
po::store(po::command_line_parser(argc, argv).
options(config).positional(inputfile).run(), vm);
po::notify(vm);

if (vm.count(“help”)) {
std::cout << cmdconfig << “\n”;
return 1;
}

if(vm.count(“filename”)) {
filename = vm[“filename”].asstd::string();
}

if(vm.count(“freq”)) {
freq = vm[“freq”].as();
}
else {
fprintf(stderr, “You must specify a frequency.\n”);
return -1;
}

if(vm.count(“rx-subdev-spec”)) {
std::string s = vm[“rx-subdev-spec”].asstd::string();
spec = str_to_subdev(s);
}

if(vm.count(“width-8”)) {
width8 = true;
}
if(vm.count(“nohb”)) {
nohb = true;
}
// if(vm.count(“output-shorts”)) {
// output_shorts = true;
// }

std::cout << "which: " << which << std::endl;
std::cout << "interp: " << interp << std::endl;
std::cout << "freq: " << freq << std::endl;
std::cout << "gain: " << gain << std::endl;
std::cout << "width-8 " << (width8 ? “Yes” : “No”) << std::endl;
std::cout << "no-hb " << (nohb ? “Yes” : “no”) << std::endl;
// std::cout << "shorts: " << (output_shorts ? “Yes” : “No”) <<
std::endl;
// std::cout << "samples: " << nsamples << std::endl;

usrp_tx_cfile_sptr top_block = make_usrp_tx_cfile(which, spec, interp,
freq,
gain, width8, nohb,
output_shorts, nsamples,
filename);
top_block->run();

return 0;
}


Here’s the command line output:

$ ~/gnuradio/gr-usrp/apps/usrp_tx_cfile -f 2500000000 in.dat
which: 0
interp: 128
freq: 2.5e+09
gain: -1
width-8 No
no-hb no

Subdevice name is A: Flex 2400 Tx MIMO B
Subdevice freq range: (2.3e+09, 2.7e+09)
mux: 0x000098
gain min is 0. gain max is 0.
No gain specified. Setting to max gain.
gain: 90
baseband rate: 1e+06
$

Here is the python version, which doesn’t seem to transmit anything:

#!/usr/bin/env python

“”"
Read samples a file and transmit using USRP

“”"

from gnuradio import gr, eng_notation
from gnuradio import audio
from gnuradio import usrp
from gnuradio.eng_option import eng_option
from optparse import OptionParser
import sys

class my_top_block(gr.top_block):

def __init__(self):
    gr.top_block.__init__(self)

    usage="%prog: [options] output_filename"
    parser = OptionParser(option_class=eng_option, usage=usage)
    parser.add_option("-R", "--tx-subdev-spec", type="subdev",

default=(0, 0),
help=“select USRP tx side A or B (default=A)”)
parser.add_option("-i", “–interp”, type=“int”, default=128,
help=“set fgpa decimation rate to INTERP
[default=%default]”)
parser.add_option("-f", “–freq”, type=“eng_float”,
default=None,
help=“set frequency to FREQ”, metavar=“FREQ”)
parser.add_option("-g", “–gain”, type=“eng_float”,
default=None,
help=“set gain in dB (default is midpoint)”)
(options, args) = parser.parse_args ()
if len(args) != 1:
parser.print_help()
raise SystemExit, 1
filename = args[0]

    if options.freq is None:
        parser.print_help()
        sys.stderr.write('You must specify the frequency with -f

FREQ\n’);
raise SystemExit, 1

    # build the graph
    self.u = usrp.sink_c(interp_rate=options.interp)
    self.src = gr.file_source(gr.sizeof_gr_complex, filename)
    self.connect(self.src, self.u)

    if options.tx_subdev_spec is None:
        options.tx_subdev_spec = usrp.pick_tx_subdevice(self.u)
    self.u.set_mux(usrp.determine_tx_mux_value(self.u,

options.tx_subdev_spec))

    # determine the daughterboard subdevice we're using
    self.subdev = usrp.selected_subdev(self.u, 

options.tx_subdev_spec)
print “Using TX d’board %s” % (self.subdev.side_and_name(),)
output_rate = self.u.dac_freq() / self.u.interp_rate()
print “USB sample rate %s” %
(eng_notation.num_to_str(output_rate))

    if options.gain is None:
        # if no gain was specified, use the mid-point in dB
        g = self.subdev.gain_range()
        options.gain = float(g[0]+g[1])/2

    print "Gain: %s" % (eng_notation.num_to_str(options.gain))

    self.subdev.set_gain(options.gain)

    r = self.u.tune(0, self.subdev, options.freq)
    if not r:
        sys.stderr.write('Failed to set frequency\n')
        raise SystemExit, 1

if name == ‘main’:
try:
my_top_block().run()
except KeyboardInterrupt:
pass

Output on command line:
$ ./usrp_tx_cfile.py -f 2500000000 -i 128 -g 90 in.dat
Using TX d’board A: Flex 2400 Tx MIMO B
USB sample rate 1M
interp: 128
gain: 90
freq: 2.5G
No bandwidth specified.


#2

On Thu, Apr 02, 2009 at 03:59:22PM -0400, Jaze Dalton wrote:

on the receiving side. To test functionality, I stored data on the Mac
using usrp_rx_cfile while running “usrp_siggen -f 2500000000” on one of the
other machines.

Also, I noticed that when I use the subdev->gain_min() and
subdev->gain_max() functions, both return 0 instead of correct values.

Those are the right values. min == max -> not adjustable

Read samples a file and transmit using USRP
class my_top_block(gr.top_block):
help="set fgpa decimation rate to INTERP

    if options.freq is None:
        parser.print_help()
        sys.stderr.write('You must specify the frequency with -f

FREQ\n’);
raise SystemExit, 1

    # build the graph
    self.u = usrp.sink_c(interp_rate=options.interp)

Try:

    self.u = usrp.sink_c(0, interp_rate=options.interp)

Eric


#3

Also, I noticed that when I use the subdev->gain_min() and
subdev->gain_max() functions, both return 0 instead of correct values.

Those are the right values. min == max -> not adjustable

I see. Thanks. So that means “self.subdev.set_gain(options.gain)” has
no
effect, right?

Mike - is this why in your usrp_replay_cfile.py file you use self.amp?

Try:

    self.u = usrp.sink_c(0, interp_rate=options.interp)

This change didn’t actually make a difference, but
self.subdev.set_enable(True) that Mike suggested did the trick. And in
fact, it’s right there in my cc file. Laughing at me for missing it.

Thanks a lot Eric and Mike!


#4

On Fri, Apr 03, 2009 at 08:18:32AM -0400, Jaze Dalton wrote:

effect, right?
On that particular daughterboard.

Eric