4098decda43cdbab4a42fd7c0fe40af365963e3e
[debian/gnuradio] / usrp / host / apps / test_usrp_standard_rx.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2003,2006,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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <getopt.h>
32 #include <assert.h>
33 #include <math.h>
34 #include "time_stuff.h"
35 #include <usrp/usrp_standard.h>
36 #include <usrp/usrp_bytesex.h>
37 #include "fpga_regs_common.h"
38 #include "fpga_regs_standard.h"
39
40 #ifdef HAVE_SCHED_H
41 #include <sched.h>
42 #endif
43
44 char *prog_name;
45
46 static bool test_input  (usrp_standard_rx_sptr urx, int max_bytes, FILE *fp);
47
48 static void
49 set_progname (char *path)
50 {
51   char *p = strrchr (path, '/');
52   if (p != 0)
53     prog_name = p+1;
54   else
55     prog_name = path;
56 }
57
58 static void
59 usage ()
60 {
61   fprintf (stderr, "usage: %s [-f] [-v] [-l] [-c] [-D <decim>] [-F freq] [-o output_file]\n", prog_name);
62   fprintf (stderr, "  [-f] loop forever\n");
63   fprintf (stderr, "  [-M] how many Megabytes to transfer (default 128)\n");
64   fprintf (stderr, "  [-v] verbose\n");
65   fprintf (stderr, "  [-l] digital loopback in FPGA\n");
66   fprintf (stderr, "  [-c] counting in FPGA\n");
67   fprintf (stderr, "  [-8] 8-bit samples across USB\n");
68   fprintf (stderr, "  [-B <fusb_block_size>] set fast usb block_size\n");
69   fprintf (stderr, "  [-N <fusb_nblocks>] set fast usb nblocks\n");
70   fprintf (stderr, "  [-R] set real time scheduling: SCHED_FIFO; pri = midpoint\n");
71
72   exit (1);
73 }
74
75 static void
76 die (const char *msg)
77 {
78   fprintf (stderr, "die: %s: %s\n", prog_name, msg);
79   exit (1);
80 }
81
82 int
83 main (int argc, char **argv)
84 {
85   bool  verbose_p = false;
86   bool  loopback_p = false;
87   bool  counting_p = false;
88   bool  width_8_p = false;
89   int   max_bytes = 128 * (1L << 20);
90   int   ch;
91   char  *output_filename = 0;
92   int   which_board = 0;
93   int   decim = 8;                      // 32 MB/sec
94   double        center_freq = 0;
95   int   fusb_block_size = 0;
96   int   fusb_nblocks = 0;
97   bool  realtime_p = false;
98
99
100   set_progname (argv[0]);
101
102   while ((ch = getopt (argc, argv, "fvlco:D:F:M:8B:N:R")) != EOF){
103     switch (ch){
104     case 'f':
105       max_bytes = 0;
106       break;
107
108     case 'v':
109       verbose_p = true;
110       break;
111
112     case 'l':
113       loopback_p = true;
114       break;
115
116     case 'c':
117       counting_p = true;
118       break;
119       
120     case '8':
121       width_8_p = true;
122       break;
123       
124     case 'o':
125       output_filename = optarg;
126       break;
127       
128     case 'D':
129       decim = strtol (optarg, 0, 0);
130       break;
131
132     case 'F':
133       center_freq = strtod (optarg, 0);
134       break;
135
136     case 'M':
137       max_bytes = strtol (optarg, 0, 0) * (1L << 20);
138       if (max_bytes < 0) max_bytes = 0;
139       break;
140
141     case 'B':
142       fusb_block_size = strtol (optarg, 0, 0);
143       break;
144
145     case 'N':
146       fusb_nblocks = strtol (optarg, 0, 0);
147       break;
148
149     case 'R':
150       realtime_p = true;
151       break;
152
153     default:
154       usage ();
155     }
156   }
157
158 #ifdef HAVE_SCHED_SETSCHEDULER
159   if (realtime_p){
160     int policy = SCHED_FIFO;
161     int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2;
162     int pid = 0;  // this process
163
164     struct sched_param param;
165     memset(&param, 0, sizeof(param));
166     param.sched_priority = pri;
167     int result = sched_setscheduler(pid, policy, &param);
168     if (result != 0){
169       perror ("sched_setscheduler: failed to set real time priority");
170     }
171     else
172       printf("SCHED_FIFO enabled with priority = %d\n", pri);
173   }
174 #endif
175
176   FILE *fp = 0;
177
178   if (output_filename){
179     fp = fopen (output_filename, "wb");
180     if (fp == 0)
181       perror (output_filename);
182   }
183       
184   int mode = 0;
185   if (loopback_p)
186     mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK;
187   if (counting_p)
188     mode |= usrp_standard_rx::FPGA_MODE_COUNTING;
189
190
191   usrp_standard_rx_sptr urx = 
192     usrp_standard_rx::make (which_board, decim, 1, -1, mode,
193                             fusb_block_size, fusb_nblocks);
194
195   if (urx == 0)
196     die ("usrp_standard_rx::make");
197
198   if (!urx->set_rx_freq (0, center_freq))
199     die ("urx->set_rx_freq");
200     
201   if (width_8_p){
202     int width = 8;
203     int shift = 8;
204     bool want_q = true;
205     if (!urx->set_format(usrp_standard_rx::make_format(width, shift, want_q)))
206       die("urx->set_format");
207   }
208
209   urx->start();         // start data xfers
210
211   test_input (urx, max_bytes, fp);
212
213   if (fp)
214     fclose (fp);
215
216   return 0;
217 }
218
219
220 static bool
221 test_input  (usrp_standard_rx_sptr urx, int max_bytes, FILE *fp)
222 {
223   int              fd = -1;
224   static const int BUFSIZE = urx->block_size();
225   static const int N = BUFSIZE/sizeof (short);
226   short            buf[N];
227   int              nbytes = 0;
228
229   double           start_wall_time = get_elapsed_time ();
230   double           start_cpu_time  = get_cpu_usage ();
231
232   if (fp)
233     fd = fileno (fp);
234   
235   bool overrun;
236   int noverruns = 0;
237
238   for (nbytes = 0; max_bytes == 0 || nbytes < max_bytes; nbytes += BUFSIZE){
239
240     unsigned int        ret = urx->read (buf, sizeof (buf), &overrun);
241     if (ret != sizeof (buf)){
242       fprintf (stderr, "test_input: error, ret = %d\n", ret);
243     }
244
245     if (overrun){
246       printf ("rx_overrun\n");
247       noverruns++;
248     }
249     
250     if (fd != -1){
251
252       for (unsigned int i = 0; i < sizeof (buf) / sizeof (short); i++)
253         buf[i] = usrp_to_host_short (buf[i]);
254
255       if (write (fd, buf, sizeof (buf)) == -1){
256         perror ("write");
257         fd = -1;
258       }
259     }
260   }
261
262   double stop_wall_time = get_elapsed_time ();
263   double stop_cpu_time  = get_cpu_usage ();
264
265   double delta_wall = stop_wall_time - start_wall_time;
266   double delta_cpu  = stop_cpu_time  - start_cpu_time;
267
268   printf ("xfered %.3g bytes in %.3g seconds.  %.4g bytes/sec.  cpu time = %.4g\n",
269           (double) max_bytes, delta_wall, max_bytes / delta_wall, delta_cpu);
270   printf ("noverruns = %d\n", noverruns);
271
272   return true;
273 }