Merged r10071:10164 from features/cppdb-test into trunk. Implements the fully native...
[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 <boost/program_options.hpp>
29
30 namespace po = boost::program_options;
31
32 usrp_subdev_spec
33 str_to_subdev(std::string spec_str)
34 {
35   usrp_subdev_spec spec;
36   if(spec_str == "A" || spec_str == "A:0" || spec_str == "0:0") {
37     spec.side = 0;
38     spec.subdev = 0;
39   }
40   else if(spec_str == "A:1" || spec_str == "0:1") {
41     spec.side = 0;
42     spec.subdev = 1;
43   }
44   else if(spec_str == "B" || spec_str == "B:0" || spec_str == "1:0") {
45     spec.side = 1;
46     spec.subdev = 0;
47   }
48   else if(spec_str == "B:1" || spec_str == "1:1") {
49     spec.side = 1;
50     spec.subdev = 1;
51   }
52   else {
53     throw std::range_error("Incorrect subdevice specifications.\n");
54   }
55
56   return spec;
57 }
58
59 // Shared pointer constructor
60 usrp_siggen_sptr make_usrp_siggen(int which, usrp_subdev_spec spec, 
61                                   double rf_freq, int interp, double wfreq,
62                                   int waveform, float amp, float gain, 
63                                   float offset)
64 {
65   return gnuradio::get_initial_sptr(new usrp_siggen(which, spec, 
66                                                     rf_freq, interp, wfreq,
67                                                     waveform, amp, gain, 
68                                                     offset));
69 }
70
71 // Hierarchical block constructor, with no inputs or outputs
72 usrp_siggen::usrp_siggen(int which, usrp_subdev_spec spec, 
73                          double rf_freq, int interp, double wfreq,
74                          int waveform, float amp, float gain, 
75                          float offset) :
76   gr_top_block("usrp_siggen")
77 {
78   usrp_sink_c_sptr usrp = usrp_make_sink_c(which, interp);
79
80   db_base_sptr subdev = usrp->selected_subdev(spec);
81   printf("Subdevice name is %s\n", subdev->name().c_str());
82   printf("Subdevice freq range: (%g, %g)\n", 
83          subdev->freq_min(), subdev->freq_max());
84
85   unsigned int mux = usrp->determine_tx_mux_value(spec);
86   printf("mux: %#08x\n",  mux);
87   usrp->set_mux(mux);
88
89   if(gain == -1) {
90     gain = subdev->gain_max();
91   }
92   subdev->set_gain(gain);
93
94   float input_rate = usrp->dac_freq() / usrp->interp_rate();
95   printf("baseband rate: %g\n",  input_rate);
96
97   usrp_tune_result r;
98   double target_freq = rf_freq;
99   bool ok = usrp->tune(subdev->which(), subdev, target_freq, &r);
100
101   if(!ok) {
102     throw std::runtime_error("Could not set frequency.");
103   }
104
105   subdev->set_enable(true);
106   
107   printf("target_freq:     %f\n", target_freq);
108   printf("ok:              %s\n", ok ? "true" : "false");
109   printf("r.baseband_freq: %f\n", r.baseband_freq);
110   printf("r.dxc_freq:      %f\n", r.dxc_freq);
111   printf("r.residual_freq: %f\n", r.residual_freq);
112   printf("r.inverted:      %d\n", r.inverted);
113
114   /* Set up the signal source */
115   siggen = gr_make_sig_source_c(input_rate, GR_SIN_WAVE, wfreq, amp);
116   noisegen = gr_make_noise_source_c (GR_UNIFORM, amp);
117   if(waveform == GR_SIN_WAVE || waveform == GR_CONST_WAVE) {
118     source = siggen;
119   }
120   else if(waveform == GR_UNIFORM || waveform == GR_GAUSSIAN) {
121     source = noisegen;
122   }
123   else {
124     throw std::range_error("Unknown waveform type.\n");
125   }
126
127   siggen->set_waveform((gr_waveform_t)waveform);
128
129   connect(source, 0, usrp, 0);
130 }
131
132 int main(int argc, char *argv[])
133 {
134   int which = 0;                       // specify which USRP board
135   usrp_subdev_spec spec(0,0);          // specify the d'board side
136   int interp = 128;                    // set the interpolation rate
137   double rf_freq = 0;                  // set the frequency
138   double wfreq = 100e3;                // set the waveform frequency
139   float amp = 5;                       // set the amplitude of the output
140   float gain = -1;                     // set the d'board PGA gain
141   float offset = 0;                    // set waveform offset
142   int waveform;
143
144   po::options_description cmdconfig("Program options");
145   cmdconfig.add_options()
146     ("help,h", "produce help message")
147     ("which,W", po::value<int>(&which), "select which USRP board")
148     ("tx-subdev-spec,T", po::value<std::string>(), "select USRP Tx side A or B")
149     ("rf-freq,f", po::value<double>(), "set RF center frequency to FREQ")
150     ("interp,i", po::value<int>(&interp), "set fgpa interpolation rate to INTERP")
151
152     ("sine", "generate a complex sinusoid [default]")
153     ("const", "generate a constant output")
154     ("gaussian", "generate Gaussian random output")
155     ("uniform", "generate Uniform random output")
156
157     ("waveform-freq,w", po::value<double>(&wfreq), "set waveform frequency to FREQ")
158     ("amplitdue,a", po::value<float>(&amp), "set amplitude")
159     ("gain,g", po::value<float>(&gain), "set output gain to GAIN")
160     ("offset,o", po::value<float>(&offset), "set waveform offset to OFFSET")
161     ;
162   
163   po::variables_map vm;
164   po::store(po::command_line_parser(argc, argv).
165             options(cmdconfig).run(), vm);
166   po::notify(vm);
167   
168   if (vm.count("help")) {
169     std::cout << cmdconfig << "\n";
170     return 1;
171   }
172   
173   if(vm.count("rf-freq")) {
174     rf_freq = vm["rf-freq"].as<double>();
175   }
176   else {
177     fprintf(stderr, "You must specify a frequency.\n");
178     return -1;
179   }
180
181   if(vm.count("tx-subdev-spec")) {
182     std::string s = vm["tx-subdev-spec"].as<std::string>();
183     spec = str_to_subdev(s);
184   }
185
186   if(vm.count("sine")) {
187     waveform = GR_SIN_WAVE;
188   }
189   else if(vm.count("const")) {
190     waveform = GR_CONST_WAVE;
191   }
192   else if(vm.count("gaussian")) {
193     waveform = GR_GAUSSIAN;
194   }
195   else if(vm.count("uniform")) {
196     waveform = GR_UNIFORM;
197   }
198   else {
199     waveform = GR_SIN_WAVE;
200   }
201
202   printf("which:   %d\n", which);
203   printf("interp:  %d\n", interp);
204   printf("rf_freq: %g\n", rf_freq);
205   printf("amp:     %f\n", amp);
206
207   usrp_siggen_sptr top_block = make_usrp_siggen(which, spec, rf_freq, 
208                                                 interp, wfreq, waveform,
209                                                 amp, gain, offset);
210
211   top_block->run();
212   
213   return 0;
214 }