Imported Upstream version 3.2.2
[debian/gnuradio] / gr-usrp / apps / usrp_siggen.cc
1 /*
2  * Copyright 2008 Free Software Foundation, Inc.
3  * 
4  * This file is part of GNU Radio
5  * 
6  * GNU Radio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  * 
11  * GNU Radio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with GNU Radio; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include <usrp_siggen.h>
23 #include <gr_io_signature.h>
24 #include <gr_head.h>
25 #include <gr_noise_type.h>
26 #include <stdexcept>
27 #include <iostream>
28 #include <cstdio>
29 #include <boost/program_options.hpp>
30
31 namespace po = boost::program_options;
32
33 usrp_subdev_spec
34 str_to_subdev(std::string spec_str)
35 {
36   usrp_subdev_spec spec;
37   if(spec_str == "A" || spec_str == "A:0" || spec_str == "0:0") {
38     spec.side = 0;
39     spec.subdev = 0;
40   }
41   else if(spec_str == "A:1" || spec_str == "0:1") {
42     spec.side = 0;
43     spec.subdev = 1;
44   }
45   else if(spec_str == "B" || spec_str == "B:0" || spec_str == "1:0") {
46     spec.side = 1;
47     spec.subdev = 0;
48   }
49   else if(spec_str == "B:1" || spec_str == "1:1") {
50     spec.side = 1;
51     spec.subdev = 1;
52   }
53   else {
54     throw std::range_error("Incorrect subdevice specifications.\n");
55   }
56
57   return spec;
58 }
59
60 // Shared pointer constructor
61 usrp_siggen_sptr make_usrp_siggen(int which, usrp_subdev_spec spec, 
62                                   double rf_freq, int interp, double wfreq,
63                                   int waveform, float amp, float gain, 
64                                   float offset, long long nsamples)
65 {
66   return gnuradio::get_initial_sptr(new usrp_siggen(which, spec, 
67                                                     rf_freq, interp, wfreq,
68                                                     waveform, amp, gain, 
69                                                     offset, nsamples));
70 }
71
72 // Hierarchical block constructor, with no inputs or outputs
73 usrp_siggen::usrp_siggen(int which, usrp_subdev_spec spec, 
74                          double rf_freq, int interp, double wfreq,
75                          int waveform, float amp, float gain, 
76                          float offset, long long nsamples)
77   : gr_top_block("usrp_siggen")
78 {
79   usrp_sink_c_sptr usrp = usrp_make_sink_c(which, interp);
80
81   db_base_sptr subdev = usrp->selected_subdev(spec);
82   printf("Subdevice name is %s\n", subdev->name().c_str());
83   printf("Subdevice freq range: (%g, %g)\n", 
84          subdev->freq_min(), subdev->freq_max());
85
86   unsigned int mux = usrp->determine_tx_mux_value(spec);
87   printf("mux: %#08x\n",  mux);
88   usrp->set_mux(mux);
89
90   if(gain == -1) {
91     gain = subdev->gain_max();
92   }
93   subdev->set_gain(gain);
94
95   float input_rate = usrp->dac_freq() / usrp->interp_rate();
96   printf("baseband rate: %g\n",  input_rate);
97
98   usrp_tune_result r;
99   double target_freq = rf_freq;
100   bool ok = usrp->tune(subdev->which(), subdev, target_freq, &r);
101
102   if(!ok) {
103     throw std::runtime_error("Could not set frequency.");
104   }
105
106   subdev->set_enable(true);
107   
108   printf("target_freq:     %f\n", target_freq);
109   printf("ok:              %s\n", ok ? "true" : "false");
110   printf("r.baseband_freq: %f\n", r.baseband_freq);
111   printf("r.dxc_freq:      %f\n", r.dxc_freq);
112   printf("r.residual_freq: %f\n", r.residual_freq);
113   printf("r.inverted:      %d\n", r.inverted);
114
115   /* Set up the signal source */
116   siggen = gr_make_sig_source_c(input_rate, GR_SIN_WAVE, wfreq, amp);
117   noisegen = gr_make_noise_source_c (GR_UNIFORM, amp);
118   if(waveform == GR_SIN_WAVE || waveform == GR_CONST_WAVE) {
119     source = siggen;
120   }
121   else if(waveform == GR_UNIFORM || waveform == GR_GAUSSIAN) {
122     source = noisegen;
123   }
124   else {
125     throw std::range_error("Unknown waveform type.\n");
126   }
127
128   siggen->set_waveform((gr_waveform_t)waveform);
129
130   if (nsamples > 0){
131     gr_block_sptr head = gr_make_head(sizeof(gr_complex), nsamples);
132     connect(source, 0, head, 0);
133     connect(head, 0, usrp, 0);
134   }
135   else {
136     connect(source, 0, usrp, 0);
137   }
138 }
139
140 int main(int argc, char *argv[])
141 {
142   int which = 0;                       // specify which USRP board
143   usrp_subdev_spec spec(0,0);          // specify the d'board side
144   int interp = 128;                    // set the interpolation rate
145   double rf_freq = 0;                  // set the frequency
146   double wfreq = 100e3;                // set the waveform frequency
147   float amp = 5;                       // set the amplitude of the output
148   float gain = -1;                     // set the d'board PGA gain
149   float offset = 0;                    // set waveform offset
150   int waveform;
151   double nsamples = 0;                 // set the number of samples to transmit (0 -> inf)
152
153   po::options_description cmdconfig("Program options");
154   cmdconfig.add_options()
155     ("help,h", "produce help message")
156     ("which,W", po::value<int>(&which), "select which USRP board")
157     ("tx-subdev-spec,T", po::value<std::string>(), "select USRP Tx side A or B")
158     ("rf-freq,f", po::value<double>(), "set RF center frequency to FREQ")
159     ("interp,i", po::value<int>(&interp), "set fgpa interpolation rate to INTERP")
160
161     ("sine", "generate a complex sinusoid [default]")
162     ("const", "generate a constant output")
163     ("gaussian", "generate Gaussian random output")
164     ("uniform", "generate Uniform random output")
165
166     ("waveform-freq,w", po::value<double>(&wfreq), "set waveform frequency to FREQ")
167     ("amplitude,a", po::value<float>(&amp), "set amplitude")
168     ("gain,g", po::value<float>(&gain), "set output gain to GAIN")
169     ("offset,o", po::value<float>(&offset), "set waveform offset to OFFSET")
170     ("nsamples,N", po::value<double>(&nsamples), "number of samples to send [default=+inf]")
171     ;
172   
173   po::variables_map vm;
174   po::store(po::command_line_parser(argc, argv).
175             options(cmdconfig).run(), vm);
176   po::notify(vm);
177   
178   if (vm.count("help")) {
179     std::cout << cmdconfig << "\n";
180     return 1;
181   }
182   
183   if(vm.count("rf-freq")) {
184     rf_freq = vm["rf-freq"].as<double>();
185   }
186   else {
187     fprintf(stderr, "You must specify a frequency.\n");
188     return -1;
189   }
190
191   if(vm.count("tx-subdev-spec")) {
192     std::string s = vm["tx-subdev-spec"].as<std::string>();
193     spec = str_to_subdev(s);
194   }
195
196   if(vm.count("sine")) {
197     waveform = GR_SIN_WAVE;
198   }
199   else if(vm.count("const")) {
200     waveform = GR_CONST_WAVE;
201   }
202   else if(vm.count("gaussian")) {
203     waveform = GR_GAUSSIAN;
204   }
205   else if(vm.count("uniform")) {
206     waveform = GR_UNIFORM;
207   }
208   else {
209     waveform = GR_SIN_WAVE;
210   }
211
212   printf("which:    %d\n", which);
213   printf("interp:   %d\n", interp);
214   printf("rf_freq:  %g\n", rf_freq);
215   printf("amp:      %f\n", amp);
216   printf("nsamples: %g\n", nsamples);
217
218   usrp_siggen_sptr top_block = make_usrp_siggen(which, spec, rf_freq, 
219                                                 interp, wfreq, waveform,
220                                                 amp, gain, offset, (long long) nsamples);
221
222   top_block->run();
223   
224   return 0;
225 }