diff options
author | jcorgan | 2006-08-03 04:51:51 +0000 |
---|---|---|
committer | jcorgan | 2006-08-03 04:51:51 +0000 |
commit | 5d69a524f81f234b3fbc41d49ba18d6f6886baba (patch) | |
tree | b71312bf7f1e8d10fef0f3ac6f28784065e73e72 /usrp/host/apps/test_usrp_standard_tx.cc | |
download | gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.gz gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.tar.bz2 gnuradio-5d69a524f81f234b3fbc41d49ba18d6f6886baba.zip |
Houston, we have a trunk.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'usrp/host/apps/test_usrp_standard_tx.cc')
-rw-r--r-- | usrp/host/apps/test_usrp_standard_tx.cc | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/usrp/host/apps/test_usrp_standard_tx.cc b/usrp/host/apps/test_usrp_standard_tx.cc new file mode 100644 index 000000000..8aebaeb8f --- /dev/null +++ b/usrp/host/apps/test_usrp_standard_tx.cc @@ -0,0 +1,319 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * 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 2, 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <usb.h> /* needed for usb functions */ +#include <getopt.h> +#include <assert.h> +#include <math.h> +#include "time_stuff.h" +#include "usrp_standard.h" +#include "usrp_bytesex.h" + +#ifdef HAVE_SCHED_H +#include <sched.h> +#endif + +char *prog_name; + +static bool test_output (usrp_standard_tx *utx, int max_bytes, double ampl, + bool dc_p, bool counting_p); + +static void +set_progname (char *path) +{ + char *p = strrchr (path, '/'); + if (p != 0) + prog_name = p+1; + else + prog_name = path; +} + +static void +usage () +{ + fprintf (stderr, + "usage: %s [-f] [-v] [-d] [-c] [-a <ampl>][-I <interp>] [-F freq] [-D]\n", prog_name); + fprintf (stderr, " [-f] loop forever\n"); + fprintf (stderr, " [-M] how many Megabytes to transfer (default 128)\n"); + fprintf (stderr, " [-v] verbose\n"); + fprintf (stderr, " [-d] dump registers\n"); + // fprintf (stderr, " [-l] digital loopback in FPGA\n"); + fprintf (stderr, " [-c] Tx counting sequence\n"); + fprintf (stderr, " [-D] DC output\n"); + + fprintf (stderr, " [-B <fusb_block_size>] set fast usb block_size\n"); + fprintf (stderr, " [-N <fusb_nblocks>] set fast usb nblocks\n"); + fprintf (stderr, " [-R] set real time scheduling: SCHED_FIFO; pri = midpoint\n"); + + exit (1); +} + +static void +die (const char *msg) +{ + fprintf (stderr, "die: %s: %s\n", prog_name, msg); + exit (1); +} + +static void +dump_codec_regs (usrp_basic *u, int which_codec, FILE *fp) +{ + for (int i = 0; i < 64; i++){ + unsigned char v; + u->_read_9862 (which_codec, i, &v); + fprintf (fp, "%2d: 0x%02x\n", i, v); + } + fflush (fp); +} + +static void +do_dump_codec_regs (usrp_basic *u) +{ + char name[100]; + strcpy (name, "regsXXXXXX"); + int fd = mkstemp (name); + if (fd == -1){ + perror (name); + } + else { + FILE *fp = fdopen (fd, "w"); + dump_codec_regs (u, 0, fp); + fclose (fp); + } +} + +int +main (int argc, char **argv) +{ + bool verbose_p = false; + bool dump_regs_p = false; + bool dc_p = false; + // bool loopback_p = false; + bool counting_p = false; + int max_bytes = 128 * (1L << 20); + int ch; + int which_board = 0; + int interp = 16; // 32.0 MB/sec + double center_freq = 0; + double ampl = 10000; + int fusb_block_size = 0; + int fusb_nblocks = 0; + bool realtime_p = false; + + + set_progname (argv[0]); + + while ((ch = getopt (argc, argv, "vfdcI:F:a:DM:B:N:R")) != EOF){ + switch (ch){ + case 'f': + max_bytes = 0; + break; + + case 'v': + verbose_p = true; + break; + + case 'd': + dump_regs_p = true; + break; + + case 'D': + dc_p = true; + break; + +#if 0 + case 'l': + loopback_p = true; + break; +#endif + + case 'c': + counting_p = true; + break; + + case 'I': + interp = strtol (optarg, 0, 0); + break; + + case 'F': + center_freq = strtod (optarg, 0); + break; + + case 'a': + ampl = strtod (optarg, 0); + break; + + case 'M': + max_bytes = strtol (optarg, 0, 0) * (1L << 20); + if (max_bytes < 0) max_bytes = 0; + break; + + case 'B': + fusb_block_size = strtol (optarg, 0, 0); + break; + + case 'N': + fusb_nblocks = strtol (optarg, 0, 0); + break; + + case 'R': + realtime_p = true; + break; + + default: + usage (); + } + } + +#ifdef HAVE_SCHED_SETSCHEDULER + if (realtime_p){ + int policy = SCHED_FIFO; + int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2; + int pid = 0; // this process + + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + perror ("sched_setscheduler: failed to set real time priority"); + } + else + printf("SCHED_FIFO enabled with priority = %d\n", pri); + } +#endif + + usrp_standard_tx *utx; + + utx = usrp_standard_tx::make (which_board, + interp, + 1, // nchan + -1, // mux + fusb_block_size, + fusb_nblocks); + + if (utx == 0) + die ("usrp_standard_tx::make"); + + if (!utx->set_tx_freq (0, center_freq)) + die ("utx->set_tx_freq"); + + if (dump_regs_p) + do_dump_codec_regs (utx); + + + fflush (stdout); + fflush (stderr); + + utx->start(); // start data xfers + + test_output (utx, max_bytes, ampl, dc_p, counting_p); + + delete utx; + + return 0; +} + + +static bool +test_output (usrp_standard_tx *utx, int max_bytes, double ampl, + bool dc_p, bool counting_p) +{ + static const int BUFSIZE = utx->block_size(); + static const int N = BUFSIZE/sizeof (short); + + short buf[N]; + int nbytes = 0; + int counter = 0; + + static const int PERIOD = 65; // any value is valid + static const int PATLEN = 2 * PERIOD; + short pattern[PATLEN]; + + for (int i = 0; i < PERIOD; i++){ + if (dc_p){ + pattern[2*i+0] = host_to_usrp_short ((short) ampl); + pattern[2*i+1] = host_to_usrp_short ((short) 0); + } + else { + pattern[2*i+0] = host_to_usrp_short ((short) (ampl * cos (2*M_PI * i / PERIOD))); + pattern[2*i+1] = host_to_usrp_short ((short) (ampl * sin (2*M_PI * i / PERIOD))); + } + } + + double start_wall_time = get_elapsed_time (); + double start_cpu_time = get_cpu_usage (); + + bool underrun; + int nunderruns = 0; + int pi = 0; + + for (nbytes = 0; max_bytes == 0 || nbytes < max_bytes; nbytes += BUFSIZE){ + + if (counting_p){ + for (int i = 0; i < N; i++) + buf[i] = host_to_usrp_short (counter++ & 0xffff); + } + else { + for (int i = 0; i < N; i++){ + buf[i] = pattern[pi]; + pi++; + if (pi >= PATLEN) + pi = 0; + } + } + + int ret = utx->write (buf, sizeof (buf), &underrun); + if ((unsigned) ret != sizeof (buf)){ + fprintf (stderr, "test_output: error, ret = %d\n", ret); + } + + if (underrun){ + nunderruns++; + printf ("tx_underrun\n"); + //printf ("tx_underrun %9d %6d\n", nbytes, nbytes/BUFSIZE); + } + } + + utx->wait_for_completion (); + + double stop_wall_time = get_elapsed_time (); + double stop_cpu_time = get_cpu_usage (); + + double delta_wall = stop_wall_time - start_wall_time; + double delta_cpu = stop_cpu_time - start_cpu_time; + + printf ("xfered %.3g bytes in %.3g seconds. %.4g bytes/sec. cpu time = %.3g\n", + (double) max_bytes, delta_wall, max_bytes / delta_wall, delta_cpu); + + printf ("%d underruns\n", nunderruns); + + return true; +} |