Added call to set antenna. Split XCVR into new thing cuz size.
[debian/gnuradio] / usrp2 / host / lib / usrp2.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008,2009 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <usrp2/usrp2.h>
24 #include "usrp2_impl.h"
25 #include <vector>
26 #include <boost/thread.hpp>
27 #include <boost/weak_ptr.hpp>
28 #include <string>
29 #include <stdexcept>
30 #include <cstdio>
31
32 namespace usrp2 {
33
34   // --- Table of weak pointers to usrps we know about ---
35
36   // (Could be cleaned up and turned into a template)
37
38   struct usrp_table_entry {
39     // inteface + normalized mac addr ("eth0:01:23:45:67:89:ab")
40     std::string key;
41     boost::weak_ptr<usrp2::usrp2>  value;
42
43     usrp_table_entry(const std::string &_key, boost::weak_ptr<usrp2::usrp2> _value)
44       : key(_key), value(_value) {}
45   };
46
47   typedef std::vector<usrp_table_entry> usrp_table;
48
49   static boost::mutex s_table_mutex;
50   static usrp_table s_table;
51
52   usrp2::sptr
53   usrp2::find_existing_or_make_new(const std::string &ifc, props *pr, size_t rx_bufsize)
54   {
55     std::string key = ifc + ":" + pr->addr;
56
57     boost::mutex::scoped_lock   guard(s_table_mutex);
58
59     for (usrp_table::iterator p = s_table.begin(); p != s_table.end();){
60       if (p->value.expired())   // weak pointer is now dead
61         p = s_table.erase(p);   // erase it
62       else {
63         if (key == p->key)      // found it
64           return usrp2::sptr(p->value);
65         else
66           ++p;                  // keep looking
67       }
68     }
69
70     // We don't have the USRP2 we're looking for
71
72     // create a new one and stick it in the table.
73     usrp2::sptr r(new usrp2::usrp2(ifc, pr, rx_bufsize));
74     usrp_table_entry t(key, r);
75     s_table.push_back(t);
76
77     return r;
78   }
79
80   // --- end of table code ---
81
82   static bool
83   parse_mac_addr(const std::string &s, std::string &ns)
84   {
85     u2_mac_addr_t p;
86
87     p.addr[0] = 0x00;           // Matt's IAB
88     p.addr[1] = 0x50;
89     p.addr[2] = 0xC2;
90     p.addr[3] = 0x85;
91     p.addr[4] = 0x30;
92     p.addr[5] = 0x00;
93
94     int len = s.size();
95     switch (len) {
96
97     case 5:
98       if (sscanf(s.c_str(), "%hhx:%hhx", &p.addr[4], &p.addr[5]) != 2)
99         return false;
100       break;
101
102     case 17:
103       if (sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
104                  &p.addr[0], &p.addr[1], &p.addr[2],
105                  &p.addr[3], &p.addr[4], &p.addr[5]) != 6)
106         return false;
107       break;
108
109     default:
110       return false;
111     }
112
113     char buf[128];
114     snprintf(buf, sizeof(buf),
115              "%02x:%02x:%02x:%02x:%02x:%02x",
116              p.addr[0],p.addr[1],p.addr[2],
117              p.addr[3],p.addr[4],p.addr[5]);
118     ns = std::string(buf);
119     return true;
120   }
121
122   usrp2::sptr
123   usrp2::make(const std::string &ifc, const std::string &addr, size_t rx_bufsize)
124   {
125     std::string naddr = "";
126     if (addr != "" && !parse_mac_addr(addr, naddr))
127       throw std::runtime_error("Invalid MAC address");
128
129     props_vector_t u2s = find(ifc, naddr);
130     int n = u2s.size();
131
132     if (n == 0) {
133       if (addr == "")
134         throw std::runtime_error("No USRPs found on interface " + ifc);
135       else
136         throw std::runtime_error("No USRP found with addr " + addr + " on interface " + ifc);
137     }
138
139     if (n > 1)
140       throw std::runtime_error("Multiple USRPs found on interface; must select by MAC address.");
141
142     return find_existing_or_make_new(ifc, &u2s[0], rx_bufsize);
143   }
144
145   // Private constructor.  Sole function is to create an impl.
146   usrp2::usrp2(const std::string &ifc, props *p, size_t rx_bufsize)
147     : d_impl(new usrp2::impl(ifc, p, rx_bufsize))
148   {
149     // NOP
150   }
151
152   // Public class destructor.  d_impl will auto-delete.
153   usrp2::~usrp2()
154   {
155     // NOP
156   }
157
158   std::string
159   usrp2::mac_addr()
160   {
161     return d_impl->mac_addr();
162   }
163
164   std::string
165   usrp2::interface_name()
166   {
167     return d_impl->interface_name();
168   }
169
170   // Receive
171
172   bool
173   usrp2::set_rx_antenna(int ant){
174     return d_impl->set_rx_antenna(ant);
175   }
176
177   bool
178   usrp2::set_rx_gain(double gain)
179   {
180     return d_impl->set_rx_gain(gain);
181   }
182
183   double
184   usrp2::rx_gain_min()
185   {
186     return d_impl->rx_gain_min();
187   }
188
189   double
190   usrp2::rx_gain_max()
191   {
192     return d_impl->rx_gain_max();
193   }
194
195   double
196   usrp2::rx_gain_db_per_step()
197   {
198     return d_impl->rx_gain_db_per_step();
199   }
200
201   bool
202   usrp2::set_rx_lo_offset(double frequency)
203   {
204     return d_impl->set_rx_lo_offset(frequency);
205   }
206
207   bool
208   usrp2::set_rx_center_freq(double frequency, tune_result *result)
209   {
210     return d_impl->set_rx_center_freq(frequency, result);
211   }
212
213   double
214   usrp2::rx_freq_min()
215   {
216     return d_impl->rx_freq_min();
217   }
218
219   double
220   usrp2::rx_freq_max()
221   {
222     return d_impl->rx_freq_max();
223   }
224
225   bool
226   usrp2::set_rx_decim(int decimation_factor)
227   {
228     return d_impl->set_rx_decim(decimation_factor);
229   }
230
231   int
232   usrp2::rx_decim()
233   {
234     return d_impl->rx_decim();
235   }
236
237   bool
238   usrp2::set_rx_scale_iq(int scale_i, int scale_q)
239   {
240     return d_impl->set_rx_scale_iq(scale_i, scale_q);
241   }
242
243   bool
244   usrp2::start_rx_streaming(unsigned int channel, unsigned int items_per_frame)
245   {
246     return d_impl->start_rx_streaming(channel, items_per_frame);
247   }
248
249   bool
250   usrp2::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
251   {
252     return d_impl->start_rx_streaming_at(channel, items_per_frame,time);
253   }
254
255   bool
256   usrp2::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
257   {
258     return d_impl->sync_and_start_rx_streaming_at(channel, items_per_frame, time);
259   }
260
261   bool
262   usrp2::rx_samples(unsigned int channel, rx_sample_handler *handler)
263   {
264     return d_impl->rx_samples(channel, handler);
265   }
266
267   bool
268   usrp2::stop_rx_streaming(unsigned int channel)
269   {
270     return d_impl->stop_rx_streaming(channel);
271   }
272
273   unsigned int
274   usrp2::rx_overruns()
275   {
276     return d_impl->rx_overruns();
277   }
278
279   unsigned int
280   usrp2::rx_missing()
281   {
282     return d_impl->rx_missing();
283   }
284
285   // Transmit
286
287   bool
288   usrp2::set_tx_antenna(int ant){
289     return d_impl->set_tx_antenna(ant);
290   }
291
292   bool
293   usrp2::set_tx_gain(double gain)
294   {
295     return d_impl->set_tx_gain(gain);
296   }
297
298   double
299   usrp2::tx_gain_min()
300   {
301     return d_impl->tx_gain_min();
302   }
303
304   double
305   usrp2::tx_gain_max()
306   {
307     return d_impl->tx_gain_max();
308   }
309
310   double
311   usrp2::tx_gain_db_per_step()
312   {
313     return d_impl->tx_gain_db_per_step();
314   }
315
316   bool
317   usrp2::set_tx_lo_offset(double frequency)
318   {
319     return d_impl->set_tx_lo_offset(frequency);
320   }
321
322   bool
323   usrp2::set_tx_center_freq(double frequency, tune_result *result)
324   {
325     return d_impl->set_tx_center_freq(frequency, result);
326   }
327
328   double
329   usrp2::tx_freq_min()
330   {
331     return d_impl->tx_freq_min();
332   }
333
334   double
335   usrp2::tx_freq_max()
336   {
337     return d_impl->tx_freq_max();
338   }
339
340
341   bool
342   usrp2::set_tx_interp(int interpolation_factor)
343   {
344     return d_impl->set_tx_interp(interpolation_factor);
345   }
346
347   int
348   usrp2::tx_interp()
349   {
350     return d_impl->tx_interp();
351   }
352
353   void
354   usrp2::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q)
355   {
356     d_impl->default_tx_scale_iq(interpolation_factor, scale_i, scale_q);
357   }
358
359   bool
360   usrp2::set_tx_scale_iq(int scale_i, int scale_q)
361   {
362     return d_impl->set_tx_scale_iq(scale_i, scale_q);
363   }
364
365   bool
366   usrp2::tx_32fc(unsigned int channel,
367                  const std::complex<float> *samples,
368                  size_t nsamples,
369                  const tx_metadata *metadata)
370   {
371     return d_impl->tx_32fc(channel, samples, nsamples, metadata);
372   }
373
374   bool
375   usrp2::tx_16sc(unsigned int channel,
376                  const std::complex<int16_t> *samples,
377                  size_t nsamples,
378                  const tx_metadata *metadata)
379   {
380     return d_impl->tx_16sc(channel, samples, nsamples, metadata);
381   }
382
383   bool
384   usrp2::tx_raw(unsigned int channel,
385                 const uint32_t *items,
386                 size_t nitems,
387                 const tx_metadata *metadata)
388   {
389     return d_impl->tx_raw(channel, items, nitems, metadata);
390   }
391
392   // miscellaneous methods
393
394   bool
395   usrp2::config_mimo(int flags)
396   {
397     return d_impl->config_mimo(flags);
398   }
399
400   bool
401   usrp2::fpga_master_clock_freq(long *freq)
402   {
403     return d_impl->fpga_master_clock_freq(freq);
404   }
405
406   bool
407   usrp2::adc_rate(long *rate)
408   {
409     return d_impl->adc_rate(rate);
410   }
411
412   bool
413   usrp2::dac_rate(long *rate)
414   {
415     return d_impl->dac_rate(rate);
416   }
417
418   bool
419   usrp2::tx_daughterboard_id(int *dbid)
420   {
421     return d_impl->tx_daughterboard_id(dbid);
422   }
423
424   bool
425   usrp2::rx_daughterboard_id(int *dbid)
426   {
427     return d_impl->rx_daughterboard_id(dbid);
428   }
429
430
431   // low level methods
432
433   bool
434   usrp2::burn_mac_addr(const std::string &new_addr)
435   {
436     return d_impl->burn_mac_addr(new_addr);
437   }
438
439   bool
440   usrp2::sync_to_pps()
441   {
442     return d_impl->sync_to_pps();
443   }
444
445   bool
446   usrp2::sync_every_pps(bool enable)
447   {
448     return d_impl->sync_every_pps(enable);
449   }
450
451   std::vector<uint32_t>
452   usrp2::peek32(uint32_t addr, uint32_t words)
453   {
454     return d_impl->peek32(addr, words);
455   }
456
457   bool
458   usrp2::poke32(uint32_t addr, const std::vector<uint32_t> &data)
459   {
460     return d_impl->poke32(addr, data);
461   }
462
463   bool
464   usrp2::set_gpio_ddr(int bank, uint16_t value, uint16_t mask)
465   {
466     return d_impl->set_gpio_ddr(bank, value, mask);
467   }
468
469   bool
470   usrp2::set_gpio_sels(int bank, std::string src)
471   {
472     return d_impl->set_gpio_sels(bank, src);
473   }
474
475   bool
476   usrp2::write_gpio(int bank, uint16_t value, uint16_t mask)
477   {
478     return d_impl->write_gpio(bank, value, mask);
479   }
480
481   bool
482   usrp2::read_gpio(int bank, uint16_t *value)
483   {
484     return d_impl->read_gpio(bank, value);
485   }
486
487   bool
488   usrp2::enable_gpio_streaming(int bank, int enable)
489   {
490     return d_impl->enable_gpio_streaming(bank, enable);
491   }
492
493 } // namespace usrp2
494
495 std::ostream& operator<<(std::ostream &os, const usrp2::props &x)
496 {
497   os << x.addr;
498
499   char buf[128];
500   snprintf(buf, sizeof(buf)," hw_rev = 0x%04x", x.hw_rev);
501
502   os << buf;
503   return os;
504 }