3 * Copyright 2008,2009 Free Software Foundation, Inc.
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.
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.
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/>.
23 #include <usrp2/usrp2.h>
24 #include "usrp2_impl.h"
26 #include <boost/thread.hpp>
27 #include <boost/weak_ptr.hpp>
34 // --- Table of weak pointers to usrps we know about ---
36 // (Could be cleaned up and turned into a template)
38 struct usrp_table_entry {
39 // inteface + normalized mac addr ("eth0:01:23:45:67:89:ab")
41 boost::weak_ptr<usrp2::usrp2> value;
43 usrp_table_entry(const std::string &_key, boost::weak_ptr<usrp2::usrp2> _value)
44 : key(_key), value(_value) {}
47 typedef std::vector<usrp_table_entry> usrp_table;
49 static boost::mutex s_table_mutex;
50 static usrp_table s_table;
53 usrp2::find_existing_or_make_new(const std::string &ifc, props *pr, size_t rx_bufsize)
55 std::string key = ifc + ":" + pr->addr;
57 boost::mutex::scoped_lock guard(s_table_mutex);
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
63 if (key == p->key) // found it
64 return usrp2::sptr(p->value);
70 // We don't have the USRP2 we're looking for
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);
80 // --- end of table code ---
83 parse_mac_addr(const std::string &s, std::string &ns)
87 p.addr[0] = 0x00; // Matt's IAB
98 if (sscanf(s.c_str(), "%hhx:%hhx", &p.addr[4], &p.addr[5]) != 2)
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)
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);
123 usrp2::make(const std::string &ifc, const std::string &addr, size_t rx_bufsize)
125 std::string naddr = "";
126 if (addr != "" && !parse_mac_addr(addr, naddr))
127 throw std::runtime_error("Invalid MAC address");
129 props_vector_t u2s = find(ifc, naddr);
134 throw std::runtime_error("No USRPs found on interface " + ifc);
136 throw std::runtime_error("No USRP found with addr " + addr + " on interface " + ifc);
140 throw std::runtime_error("Multiple USRPs found on interface; must select by MAC address.");
142 return find_existing_or_make_new(ifc, &u2s[0], rx_bufsize);
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))
152 // Public class destructor. d_impl will auto-delete.
161 return d_impl->mac_addr();
165 usrp2::interface_name()
167 return d_impl->interface_name();
173 usrp2::set_rx_gain(double gain)
175 return d_impl->set_rx_gain(gain);
181 return d_impl->rx_gain_min();
187 return d_impl->rx_gain_max();
191 usrp2::rx_gain_db_per_step()
193 return d_impl->rx_gain_db_per_step();
197 usrp2::set_rx_lo_offset(double frequency)
199 return d_impl->set_rx_lo_offset(frequency);
203 usrp2::set_rx_center_freq(double frequency, tune_result *result)
205 return d_impl->set_rx_center_freq(frequency, result);
211 return d_impl->rx_freq_min();
217 return d_impl->rx_freq_max();
221 usrp2::set_rx_decim(int decimation_factor)
223 return d_impl->set_rx_decim(decimation_factor);
229 return d_impl->rx_decim();
233 usrp2::set_rx_scale_iq(int scale_i, int scale_q)
235 return d_impl->set_rx_scale_iq(scale_i, scale_q);
239 usrp2::start_rx_streaming(unsigned int channel, unsigned int items_per_frame)
241 return d_impl->start_rx_streaming(channel, items_per_frame);
245 usrp2::rx_samples(unsigned int channel, rx_sample_handler *handler)
247 return d_impl->rx_samples(channel, handler);
251 usrp2::stop_rx_streaming(unsigned int channel)
253 return d_impl->stop_rx_streaming(channel);
259 return d_impl->rx_overruns();
265 return d_impl->rx_missing();
271 usrp2::set_tx_gain(double gain)
273 return d_impl->set_tx_gain(gain);
279 return d_impl->tx_gain_min();
285 return d_impl->tx_gain_max();
289 usrp2::tx_gain_db_per_step()
291 return d_impl->tx_gain_db_per_step();
295 usrp2::set_tx_lo_offset(double frequency)
297 return d_impl->set_tx_lo_offset(frequency);
301 usrp2::set_tx_center_freq(double frequency, tune_result *result)
303 return d_impl->set_tx_center_freq(frequency, result);
309 return d_impl->tx_freq_min();
315 return d_impl->tx_freq_max();
320 usrp2::set_tx_interp(int interpolation_factor)
322 return d_impl->set_tx_interp(interpolation_factor);
328 return d_impl->tx_interp();
332 usrp2::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q)
334 d_impl->default_tx_scale_iq(interpolation_factor, scale_i, scale_q);
338 usrp2::set_tx_scale_iq(int scale_i, int scale_q)
340 return d_impl->set_tx_scale_iq(scale_i, scale_q);
344 usrp2::tx_32fc(unsigned int channel,
345 const std::complex<float> *samples,
347 const tx_metadata *metadata)
349 return d_impl->tx_32fc(channel, samples, nsamples, metadata);
353 usrp2::tx_16sc(unsigned int channel,
354 const std::complex<int16_t> *samples,
356 const tx_metadata *metadata)
358 return d_impl->tx_16sc(channel, samples, nsamples, metadata);
362 usrp2::tx_raw(unsigned int channel,
363 const uint32_t *items,
365 const tx_metadata *metadata)
367 return d_impl->tx_raw(channel, items, nitems, metadata);
370 // miscellaneous methods
373 usrp2::config_mimo(int flags)
375 return d_impl->config_mimo(flags);
379 usrp2::fpga_master_clock_freq(long *freq)
381 return d_impl->fpga_master_clock_freq(freq);
385 usrp2::adc_rate(long *rate)
387 return d_impl->adc_rate(rate);
391 usrp2::dac_rate(long *rate)
393 return d_impl->dac_rate(rate);
397 usrp2::tx_daughterboard_id(int *dbid)
399 return d_impl->tx_daughterboard_id(dbid);
403 usrp2::rx_daughterboard_id(int *dbid)
405 return d_impl->rx_daughterboard_id(dbid);
412 usrp2::burn_mac_addr(const std::string &new_addr)
414 return d_impl->burn_mac_addr(new_addr);
420 return d_impl->sync_to_pps();
424 usrp2::sync_every_pps(bool enable)
426 return d_impl->sync_every_pps(enable);
429 std::vector<uint32_t>
430 usrp2::peek32(uint32_t addr, uint32_t words)
432 return d_impl->peek32(addr, words);
436 usrp2::poke32(uint32_t addr, const std::vector<uint32_t> &data)
438 return d_impl->poke32(addr, data);
442 usrp2::set_gpio_ddr(int bank, uint16_t value, uint16_t mask)
444 return d_impl->set_gpio_ddr(bank, value, mask);
448 usrp2::set_gpio_sels(int bank, std::string src)
450 return d_impl->set_gpio_sels(bank, src);
454 usrp2::write_gpio(int bank, uint16_t value, uint16_t mask)
456 return d_impl->write_gpio(bank, value, mask);
460 usrp2::read_gpio(int bank, uint16_t *value)
462 return d_impl->read_gpio(bank, value);
466 usrp2::enable_gpio_streaming(int bank, int enable)
468 return d_impl->enable_gpio_streaming(bank, enable);
473 std::ostream& operator<<(std::ostream &os, const usrp2::props &x)
478 snprintf(buf, sizeof(buf)," hw_rev = 0x%04x", x.hw_rev);