X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=usrp%2Fhost%2Fapps%2Ftest_usrp_standard_tx.cc;h=3cc20c4472a7e4988bc3663c1cbd45c02f4338e1;hb=ea29b08aeb54227e6628f655ccfdb96fe4d8c378;hp=6418c4abff1327df106371aa36efa4b82b5f8705;hpb=09a1e803a9e6587c78d20cdf16891e5295874668;p=debian%2Fgnuradio diff --git a/usrp/host/apps/test_usrp_standard_tx.cc b/usrp/host/apps/test_usrp_standard_tx.cc index 6418c4ab..3cc20c44 100644 --- a/usrp/host/apps/test_usrp_standard_tx.cc +++ b/usrp/host/apps/test_usrp_standard_tx.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003,2004 Free Software Foundation, Inc. + * Copyright 2003,2004,2008,2009 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,6 +24,7 @@ #include "config.h" #endif +#include #include #include #include @@ -35,15 +36,44 @@ #include "time_stuff.h" #include "usrp_standard.h" #include "usrp_bytesex.h" +#include -#ifdef HAVE_SCHED_H -#include -#endif +enum { + GR_SIN_WAVE, + GR_CONST_WAVE +}; + +namespace po = boost::program_options; char *prog_name; -static bool test_output (usrp_standard_tx *utx, int max_bytes, double ampl, - bool dc_p, bool counting_p); +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; +} + static void set_progname (char *path) @@ -55,26 +85,6 @@ set_progname (char *path) prog_name = path; } -static void -usage () -{ - fprintf (stderr, - "usage: %s [-f] [-v] [-d] [-c] [-a ][-I ] [-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 ] set fast usb block_size\n"); - fprintf (stderr, " [-N ] 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) { @@ -82,137 +92,154 @@ die (const char *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) +static bool +test_output (usrp_standard_tx_sptr utx, long long max_bytes, double ampl, int waveform) { - char name[100]; - strcpy (name, "regsXXXXXX"); - int fd = mkstemp (name); - if (fd == -1){ - perror (name); + const int BUFSIZE = utx->block_size(); + const int N = BUFSIZE/sizeof (short); + + short buf[N]; + long long nbytes = 0; + + // ---------------------------------------------------------------- + // one time initialization of the pattern we're going to transmit + + const int PERIOD = 65; // any value is valid + const int PATLEN = 2 * PERIOD; + short pattern[PATLEN]; + + for (int i = 0; i < PERIOD; i++){ + if (waveform == GR_CONST_WAVE){ + 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))); + } } - else { - FILE *fp = fdopen (fd, "w"); - dump_codec_regs (u, 0, fp); - fclose (fp); + + // ---------------------------------------------------------------- + + 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){ + + 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; } 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 which = 0; // specify which USRP board + usrp_subdev_spec spec(0,0); // specify the d'board side + int interp = 16; // set the interpolation rate + double rf_freq = -1; // set the frequency + float amp = 10000; // set the amplitude of the output + float gain = -1; // set the d'board PGA gain + int waveform; int fusb_block_size = 0; int fusb_nblocks = 0; bool realtime_p = false; - + double nsamples = 32e6; 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; + po::options_description cmdconfig("Program options"); + cmdconfig.add_options() + ("help,h", "produce help message") + ("which,W", po::value(&which), "select which USRP board") + ("tx-subdev-spec,T", po::value(), "select USRP Tx side A or B") + ("rf-freq,f", po::value(), "set RF center frequency to FREQ") + ("interp,i", po::value(&interp), "set fgpa interpolation rate to INTERP") + + ("sine", "generate a complex sinusoid [default]") + ("const", "generate a constant output") + + //("waveform-freq,w", po::value(&wfreq), "set waveform frequency to FREQ") + ("amplitude,a", po::value(&), "set amplitude") + ("gain,g", po::value(&gain), "set output gain to GAIN [default=MAX]") + //("offset,o", po::value(&offset), "set waveform offset to OFFSET") + ("nsamples,N", po::value(&nsamples), "number of samples to send [default=32M]") + ; + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv). + options(cmdconfig).run(), vm); + po::notify(vm); + + if (vm.count("help")) { + std::cout << cmdconfig << "\n"; + return 1; + } + + if(vm.count("tx-subdev-spec")) { + std::string s = vm["tx-subdev-spec"].as(); + spec = str_to_subdev(s); + } - case 'N': - fusb_nblocks = strtol (optarg, 0, 0); - break; + if(vm.count("sine")) { + waveform = GR_SIN_WAVE; + } + else if(vm.count("const")) { + waveform = GR_CONST_WAVE; + } + else { + waveform = GR_SIN_WAVE; + } - case 'R': - realtime_p = true; - break; + printf("which: %d\n", which); + printf("interp: %d\n", interp); + printf("rf_freq: %g\n", rf_freq); + printf("amp: %f\n", amp); + printf("nsamples: %g\n", nsamples); - 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); + // FIXME } -#endif - usrp_standard_tx *utx; + usrp_standard_tx_sptr utx; - utx = usrp_standard_tx::make (which_board, + utx = usrp_standard_tx::make (which, interp, 1, // nchan -1, // mux @@ -221,99 +248,68 @@ main (int argc, char **argv) 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 + // FIXME - test_output (utx, max_bytes, ampl, dc_p, counting_p); + db_base_sptr subdev = utx->selected_subdev(spec); + printf("Subdevice name is %s\n", subdev->name().c_str()); + printf("Subdevice freq range: (%g, %g)\n", + subdev->freq_min(), subdev->freq_max()); - delete utx; + unsigned int mux = utx->determine_tx_mux_value(spec); + printf("mux: %#08x\n", mux); + utx->set_mux(mux); - return 0; -} + if(gain == -1) + gain = subdev->gain_max(); + subdev->set_gain(gain); + float input_rate = utx->dac_rate() / utx->interp_rate(); + printf("baseband rate: %g\n", input_rate); -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; + usrp_tune_result r; - static const int PERIOD = 65; // any value is valid - static const int PATLEN = 2 * PERIOD; - short pattern[PATLEN]; + if (rf_freq < 0) + rf_freq = (subdev->freq_min() + subdev->freq_max()) * 0.5; + double target_freq = rf_freq; + bool ok = utx->tune(subdev->which(), subdev, target_freq, &r); - 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))); - } + if(!ok) { + throw std::runtime_error("Could not set frequency."); } - double start_wall_time = get_elapsed_time (); - double start_cpu_time = get_cpu_usage (); - - bool underrun; - int nunderruns = 0; - int pi = 0; + subdev->set_enable(true); + + printf("target_freq: %f\n", target_freq); + printf("ok: %s\n", ok ? "true" : "false"); + printf("r.baseband_freq: %f\n", r.baseband_freq); + printf("r.dxc_freq: %f\n", r.dxc_freq); + printf("r.residual_freq: %f\n", r.residual_freq); + printf("r.inverted: %d\n", r.inverted); - 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; - } - } + fflush (stdout); + fflush (stderr); - int ret = utx->write (buf, sizeof (buf), &underrun); - if ((unsigned) ret != sizeof (buf)){ - fprintf (stderr, "test_output: error, ret = %d\n", ret); - } + utx->start(); // start data xfers - if (underrun){ - nunderruns++; - printf ("tx_underrun\n"); - //printf ("tx_underrun %9d %6d\n", nbytes, nbytes/BUFSIZE); - } - } + test_output (utx, (long long) nsamples, amp, waveform); - utx->wait_for_completion (); + return 0; +} - 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; +#if 0 + case 'B': + fusb_block_size = strtol (optarg, 0, 0); + break; - 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); + case 'N': + fusb_nblocks = strtol (optarg, 0, 0); + break; - printf ("%d underruns\n", nunderruns); + case 'R': + realtime_p = true; + break; - return true; -} +#endif