Statistics
| Branch: | Tag: | Revision:

root / usrp / host / apps / test_usrp_standard_tx.cc @ c276a4ff

History | View | Annotate | Download (8 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include <iostream>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
#include <unistd.h>
32
#include <usb.h>                        /* needed for usb functions */
33
#include <getopt.h>
34
#include <assert.h>
35
#include <math.h>
36
#include "time_stuff.h"
37
#include <usrp/usrp_standard.h>
38
#include <usrp/usrp_bytesex.h>
39
#include <boost/program_options.hpp>
40
41
enum {
42
  GR_SIN_WAVE,
43
  GR_CONST_WAVE
44
};
45
46
namespace po = boost::program_options;
47
48
char *prog_name;
49
50
usrp_subdev_spec
51
str_to_subdev(std::string spec_str)
52
{
53
  usrp_subdev_spec spec;
54
  if(spec_str == "A" || spec_str == "A:0" || spec_str == "0:0") {
55
    spec.side = 0;
56
    spec.subdev = 0;
57
  }
58
  else if(spec_str == "A:1" || spec_str == "0:1") {
59
    spec.side = 0;
60
    spec.subdev = 1;
61
  }
62
  else if(spec_str == "B" || spec_str == "B:0" || spec_str == "1:0") {
63
    spec.side = 1;
64
    spec.subdev = 0;
65
  }
66
  else if(spec_str == "B:1" || spec_str == "1:1") {
67
    spec.side = 1;
68
    spec.subdev = 1;
69
  }
70
  else {
71
    throw std::range_error("Incorrect subdevice specifications.\n");
72
  }
73
74
  return spec;
75
}
76
77
78
static void
79
set_progname (char *path)
80
{
81
  char *p = strrchr (path, '/');
82
  if (p != 0)
83
    prog_name = p+1;
84
  else
85
    prog_name = path;
86
}
87
88
static void
89
die (const char *msg)
90
{
91
  fprintf (stderr, "die: %s: %s\n", prog_name, msg);
92
  exit (1);
93
}
94
95
96
static bool
97
test_output (usrp_standard_tx_sptr utx, long long max_bytes, double ampl, int waveform)
98
{
99
  const int BUFSIZE = utx->block_size();
100
  const int N = BUFSIZE/sizeof (short);
101
102
  short            buf[N];
103
  long long        nbytes = 0;
104
105
  // ----------------------------------------------------------------
106
  // one time initialization of the pattern we're going to transmit
107
108
  const int        PERIOD = 65;                // any value is valid
109
  const int            PATLEN = 2 * PERIOD;        
110
  short                       pattern[PATLEN];
111
112
  for (int i = 0; i < PERIOD; i++){
113
    if (waveform == GR_CONST_WAVE){
114
      pattern[2*i+0] = host_to_usrp_short((short) ampl);
115
      pattern[2*i+1] = host_to_usrp_short((short) 0);
116
    }
117
    else {
118
      pattern[2*i+0] = host_to_usrp_short((short) (ampl * cos(2*M_PI * i / PERIOD)));
119
      pattern[2*i+1] = host_to_usrp_short((short) (ampl * sin(2*M_PI * i / PERIOD)));
120
    }
121
  }
122
123
  // ----------------------------------------------------------------
124
125
  double start_wall_time = get_elapsed_time ();
126
  double start_cpu_time  = get_cpu_usage ();
127
128
  bool         underrun;
129
  int         nunderruns = 0;
130
  int         pi = 0;
131
132
  for (nbytes = 0; max_bytes == 0 || nbytes < max_bytes; nbytes += BUFSIZE){
133
134
    for (int i = 0; i < N; i++){
135
      buf[i] = pattern[pi];
136
      pi++;
137
      if (pi >= PATLEN)
138
        pi = 0;
139
    }
140
141
    int        ret = utx->write (buf, sizeof (buf), &underrun);
142
    if ((unsigned) ret != sizeof (buf)){
143
      fprintf (stderr, "test_output: error, ret = %d\n", ret);
144
    }
145
146
    if (underrun){
147
      nunderruns++;
148
      printf ("tx_underrun\n");
149
      //printf ("tx_underrun %9d %6d\n", nbytes, nbytes/BUFSIZE);
150
    }
151
  }
152
153
  utx->wait_for_completion ();
154
155
  double stop_wall_time = get_elapsed_time ();
156
  double stop_cpu_time  = get_cpu_usage ();
157
158
  double delta_wall = stop_wall_time - start_wall_time;
159
  double delta_cpu  = stop_cpu_time  - start_cpu_time;
160
161
  printf ("xfered %.3g bytes in %.3g seconds.  %.4g bytes/sec.  cpu time = %.3g\n",
162
          (double) max_bytes, delta_wall, max_bytes / delta_wall, delta_cpu);
163
164
  printf ("%d underruns\n", nunderruns);
165
166
  return true;
167
}
168
169
int
170
main (int argc, char **argv)
171
{
172
  int which = 0;                       // specify which USRP board
173
  usrp_subdev_spec spec(0,0);          // specify the d'board side
174
  int interp = 16;                     // set the interpolation rate
175
  double rf_freq = -1;                 // set the frequency
176
  float amp = 10000;                   // set the amplitude of the output
177
  float gain = -1;                     // set the d'board PGA gain
178
  int waveform;
179
  int        fusb_block_size = 0;
180
  int        fusb_nblocks = 0;
181
  bool        realtime_p = false;
182
  double nsamples = 32e6;
183
184
  set_progname (argv[0]);
185
186
  po::options_description cmdconfig("Program options");
187
  cmdconfig.add_options()
188
    ("help,h", "produce help message")
189
    ("which,W", po::value<int>(&which), "select which USRP board")
190
    ("tx-subdev-spec,T", po::value<std::string>(), "select USRP Tx side A or B")
191
    ("rf-freq,f", po::value<double>(), "set RF center frequency to FREQ")
192
    ("interp,i", po::value<int>(&interp), "set fgpa interpolation rate to INTERP")
193
194
    ("sine", "generate a complex sinusoid [default]")
195
    ("const", "generate a constant output")
196
197
    //("waveform-freq,w", po::value<double>(&wfreq), "set waveform frequency to FREQ")
198
    ("amplitude,a", po::value<float>(&amp), "set amplitude")
199
    ("gain,g", po::value<float>(&gain), "set output gain to GAIN [default=MAX]")
200
    //("offset,o", po::value<float>(&offset), "set waveform offset to OFFSET")
201
    ("nsamples,N", po::value<double>(&nsamples), "number of samples to send [default=32M]")
202
    ;
203
  
204
  po::variables_map vm;
205
  po::store(po::command_line_parser(argc, argv).
206
            options(cmdconfig).run(), vm);
207
  po::notify(vm);
208
  
209
  if (vm.count("help")) {
210
    std::cout << cmdconfig << "\n";
211
    return 1;
212
  }
213
  
214
  if(vm.count("tx-subdev-spec")) {
215
    std::string s = vm["tx-subdev-spec"].as<std::string>();
216
    spec = str_to_subdev(s);
217
  }
218
219
  if(vm.count("sine")) {
220
    waveform = GR_SIN_WAVE;
221
  }
222
  else if(vm.count("const")) {
223
    waveform = GR_CONST_WAVE;
224
  }
225
  else {
226
    waveform = GR_SIN_WAVE;
227
  }
228
229
  printf("which:    %d\n", which);
230
  printf("interp:   %d\n", interp);
231
  printf("rf_freq:  %g\n", rf_freq);
232
  printf("amp:      %f\n", amp);
233
  printf("nsamples: %g\n", nsamples);
234
235
236
  if (realtime_p){
237
    // FIXME
238
  }
239
240
  usrp_standard_tx_sptr utx;
241
242
  utx = usrp_standard_tx::make (which,
243
                                interp,
244
                                1,         // nchan
245
                                -1,         // mux
246
                                fusb_block_size,
247
                                fusb_nblocks);
248
249
  if (utx == 0)
250
    die ("usrp_standard_tx::make");
251
252
  // FIXME
253
254
  db_base_sptr subdev = utx->selected_subdev(spec);
255
  printf("Subdevice name is %s\n", subdev->name().c_str());
256
  printf("Subdevice freq range: (%g, %g)\n", 
257
         subdev->freq_min(), subdev->freq_max());
258
259
  unsigned int mux = utx->determine_tx_mux_value(spec);
260
  printf("mux: %#08x\n",  mux);
261
  utx->set_mux(mux);
262
263
  if(gain == -1)
264
    gain = subdev->gain_max();
265
  subdev->set_gain(gain);
266
267
  float input_rate = utx->dac_rate() / utx->interp_rate();
268
  printf("baseband rate: %g\n",  input_rate);
269
270
  usrp_tune_result r;
271
272
  if (rf_freq < 0)
273
    rf_freq = (subdev->freq_min() + subdev->freq_max()) * 0.5;
274
  double target_freq = rf_freq;
275
  bool ok = utx->tune(subdev->which(), subdev, target_freq, &r);
276
277
  if(!ok) {
278
    throw std::runtime_error("Could not set frequency.");
279
  }
280
281
  subdev->set_enable(true);
282
  
283
  printf("target_freq:     %f\n", target_freq);
284
  printf("ok:              %s\n", ok ? "true" : "false");
285
  printf("r.baseband_freq: %f\n", r.baseband_freq);
286
  printf("r.dxc_freq:      %f\n", r.dxc_freq);
287
  printf("r.residual_freq: %f\n", r.residual_freq);
288
  printf("r.inverted:      %d\n", r.inverted);
289
290
291
  fflush (stdout);
292
  fflush (stderr);
293
294
  utx->start();                // start data xfers
295
296
  test_output (utx, (long long) nsamples, amp, waveform);
297
298
  return 0;
299
}  
300
301
302
#if 0
303
    case 'B':
304
      fusb_block_size = strtol (optarg, 0, 0);
305
      break;
306
307
    case 'N':
308
      fusb_nblocks = strtol (optarg, 0, 0);
309
      break;
310
311
    case 'R':
312
      realtime_p = true;
313
      break;
314
315
#endif