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