Imported Upstream version 3.2.2
[debian/gnuradio] / gr-usrp / src / usrp_sink_base.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2008 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 <usrp_sink_base.h>
28 #include <gr_io_signature.h>
29 #include <usrp_standard.h>
30 #include <assert.h>
31 #include <cstdio>
32
33 static const int OUTPUT_MULTIPLE_SAMPLES = 128;         // DON'T CHANGE THIS VALUE!
34
35 usrp_sink_base::usrp_sink_base (const std::string &name,
36                                   gr_io_signature_sptr input_signature,
37                                   int which_board,
38                                   unsigned int interp_rate,
39                                   int nchan,
40                                   int mux,
41                                   int fusb_block_size,
42                                   int fusb_nblocks,
43                                   const std::string fpga_filename,
44                                   const std::string firmware_filename
45                                   ) throw (std::runtime_error)
46   : usrp_base(name,
47               input_signature,
48               gr_make_io_signature (0, 0, 0)),
49     d_nunderruns (0)
50 {
51   d_usrp = usrp_standard_tx::make (which_board,
52                                    interp_rate,
53                                    nchan, mux,
54                                    fusb_block_size,
55                                    fusb_nblocks,
56                                    fpga_filename,
57                                    firmware_filename
58                                    );
59   if (d_usrp == 0)
60     throw std::runtime_error ("can't open usrp");
61
62   set_usrp_basic(d_usrp);
63
64   // All calls to d_usrp->write must be multiples of 512 bytes.
65
66   set_output_multiple (OUTPUT_MULTIPLE_SAMPLES);
67 }
68
69 usrp_sink_base::~usrp_sink_base ()
70 {
71 }
72
73 int
74 usrp_sink_base::work (int noutput_items,
75                        gr_vector_const_void_star &input_items,
76                        gr_vector_void_star &output_items)
77 {
78   static const int BUFSIZE = 16 * (1L << 10);   // 16kB
79   unsigned char outbuf[BUFSIZE];
80   int           obi = 0;
81   int           input_index = 0;
82   int           input_items_consumed;
83   int           bytes_written;
84   bool          underrun;
85   
86
87   while (input_index < noutput_items){
88   
89     copy_to_usrp_buffer (input_items,
90                          input_index,
91                          noutput_items - input_index,   // input_items_available
92                          input_items_consumed,          // [out]
93                          &outbuf[obi],                  // [out] usrp_buffer
94                          BUFSIZE - obi,                 // usrp_buffer_length
95                          bytes_written);                // [out]
96
97     assert (input_index + input_items_consumed <= noutput_items);
98     assert (obi + bytes_written <= BUFSIZE);
99     
100     input_index += input_items_consumed;
101     obi += bytes_written;
102
103     if (obi >= BUFSIZE){        // flush
104       if (d_usrp->write (outbuf, obi, &underrun) != obi)
105         return -1;              // indicate we're done
106
107       if (underrun){
108         d_nunderruns++;
109         // fprintf (stderr, "usrp_sink: underrun\n");
110         fputs ("uU", stderr);
111       }
112       obi = 0;
113     }
114   }
115
116   if (obi != 0){
117     assert (obi % 512 == 0);
118     if (d_usrp->write (outbuf, obi, &underrun) != obi)
119       return -1;        // indicate we're done
120
121     if (underrun){
122       d_nunderruns++;
123       // fprintf (stderr, "usrp_sink: underrun\n");
124       fputs ("uU", stderr);
125     }
126   }
127
128   return noutput_items;
129 }
130
131 bool
132 usrp_sink_base::set_interp_rate (unsigned int rate)
133 {
134   return d_usrp->set_interp_rate (rate);
135 }
136
137 bool
138 usrp_sink_base::set_nchannels (int nchan)
139 {
140   return d_usrp->set_nchannels (nchan);
141 }
142
143 bool
144 usrp_sink_base::set_mux (int mux)
145 {
146   return d_usrp->set_mux (mux);
147 }
148
149 int
150 usrp_sink_base::determine_tx_mux_value(usrp_subdev_spec ss)
151 {
152   return d_usrp->determine_tx_mux_value(ss);
153 }
154
155 int
156 usrp_sink_base::determine_tx_mux_value(usrp_subdev_spec ss_a, usrp_subdev_spec ss_b)
157 {
158   return d_usrp->determine_tx_mux_value(ss_a, ss_b);
159 }
160
161 bool
162 usrp_sink_base::set_tx_freq (int channel, double freq)
163 {
164   return d_usrp->set_tx_freq (channel, freq);
165 }
166
167 unsigned int
168 usrp_sink_base::interp_rate () const
169 {
170   return d_usrp->interp_rate ();
171 }
172
173 int
174 usrp_sink_base::nchannels () const
175 {
176   return d_usrp->nchannels ();
177 }
178
179 int
180 usrp_sink_base::mux () const
181 {
182   return d_usrp->mux ();
183 }
184
185
186 double
187 usrp_sink_base::tx_freq (int channel) const
188 {
189   return d_usrp->tx_freq (channel);
190 }
191
192 bool
193 usrp_sink_base::has_rx_halfband()
194 {
195   return d_usrp->has_rx_halfband();
196 }
197  
198 bool
199 usrp_sink_base::has_tx_halfband()
200 {
201   return d_usrp->has_tx_halfband();
202 }
203
204 int
205 usrp_sink_base::nddcs()
206 {
207   return d_usrp->nddcs();
208 }
209
210 int
211 usrp_sink_base::nducs()
212 {
213   return d_usrp->nducs();
214 }
215
216 bool
217 usrp_sink_base::start()
218 {
219   return d_usrp->start();
220 }
221
222 bool
223 usrp_sink_base::stop()
224 {
225   return d_usrp->stop();
226 }
227
228
229 bool
230 usrp_sink_base::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result)
231 {
232   return d_usrp->tune(chan, db, target_freq, result);
233 }
234
235 usrp_subdev_spec
236 usrp_sink_base::pick_tx_subdevice()
237 {
238   int dbids[] = {
239     USRP_DBID_FLEX_400_TX,
240     USRP_DBID_FLEX_900_TX,
241     USRP_DBID_FLEX_1200_TX,
242     USRP_DBID_FLEX_2400_TX,
243     USRP_DBID_BASIC_TX
244   };
245
246   std::vector<int> candidates(dbids, dbids+(sizeof(dbids)/sizeof(int)));
247   return pick_subdev(candidates);
248 }