Statistics
| Branch: | Tag: | Revision:

root / host / lib / usrp / usrp2 / usrp2_impl.cpp @ 51a9c2d4

History | View | Annotate | Download (6.65 KB)

1
//
2
// Copyright 2010 Ettus Research LLC
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

    
18
#include "usrp2_impl.hpp"
19
#include <uhd/transport/if_addrs.hpp>
20
#include <uhd/transport/udp_simple.hpp>
21
#include <uhd/usrp/device_props.hpp>
22
#include <uhd/utils/assert.hpp>
23
#include <uhd/utils/static.hpp>
24
#include <boost/assign/list_of.hpp>
25
#include <boost/format.hpp>
26
#include <boost/foreach.hpp>
27
#include <boost/bind.hpp>
28
#include <boost/asio.hpp> //htonl and ntohl
29
#include <iostream>
30

    
31
using namespace uhd;
32
using namespace uhd::usrp;
33
using namespace uhd::transport;
34
namespace asio = boost::asio;
35

    
36
UHD_STATIC_BLOCK(register_usrp2_device){
37
    device::register_device(&usrp2::find, &usrp2::make);
38
}
39

    
40
/***********************************************************************
41
 * Discovery over the udp transport
42
 **********************************************************************/
43
uhd::device_addrs_t usrp2::find(const device_addr_t &hint){
44
    device_addrs_t usrp2_addrs;
45

    
46
    //if no address was specified, send a broadcast on each interface
47
    if (not hint.has_key("addr")){
48
        BOOST_FOREACH(const if_addrs_t &if_addrs, get_if_addrs()){
49
            //avoid the loopback device
50
            if (if_addrs.inet == asio::ip::address_v4::loopback().to_string()) continue;
51

    
52
            //create a new hint with this broadcast address
53
            device_addr_t new_hint = hint;
54
            new_hint["addr"] = if_addrs.bcast;
55

    
56
            //call discover with the new hint and append results
57
            device_addrs_t new_usrp2_addrs = usrp2::find(new_hint);
58
            usrp2_addrs.insert(usrp2_addrs.begin(),
59
                new_usrp2_addrs.begin(), new_usrp2_addrs.end()
60
            );
61
        }
62
        return usrp2_addrs;
63
    }
64

    
65
    //create a udp transport to communicate
66
    std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT);
67
    udp_simple::sptr udp_transport = udp_simple::make_broadcast(
68
        hint["addr"], ctrl_port
69
    );
70

    
71
    //send a hello control packet
72
    usrp2_ctrl_data_t ctrl_data_out;
73
    ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO);
74
    udp_transport->send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out)));
75

    
76
    //loop and recieve until the timeout
77
    while(true){
78
        usrp2_ctrl_data_t ctrl_data_in;
79
        size_t len = udp_transport->recv(asio::buffer(&ctrl_data_in, sizeof(ctrl_data_in)));
80
        //std::cout << len << "\n";
81
        if (len >= sizeof(usrp2_ctrl_data_t)){
82
            //handle the received data
83
            switch(ntohl(ctrl_data_in.id)){
84
            case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE:
85
                //make a boost asio ipv4 with the raw addr in host byte order
86
                boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in.data.ip_addr));
87
                device_addr_t new_addr;
88
                new_addr["name"] = "USRP2";
89
                new_addr["addr"] = ip_addr.to_string();
90
                usrp2_addrs.push_back(new_addr);
91
                //dont break here, it will exit the while loop
92
                //just continue on to the next loop iteration
93
            }
94
        }
95
        if (len == 0) break; //timeout
96
    }
97

    
98
    return usrp2_addrs;
99
}
100

    
101
/***********************************************************************
102
 * Make
103
 **********************************************************************/
104
template <class T> std::string num2str(T num){
105
    return boost::lexical_cast<std::string>(num);
106
}
107

    
108
device::sptr usrp2::make(const device_addr_t &device_addr){
109
    //create a control transport
110
    udp_simple::sptr ctrl_transport = udp_simple::make_connected(
111
        device_addr["addr"], num2str(USRP2_UDP_CTRL_PORT)
112
    );
113

    
114
    //create a data transport
115
    udp_zero_copy::sptr data_transport = udp_zero_copy::make(
116
        device_addr["addr"], num2str(USRP2_UDP_DATA_PORT)
117
    );
118

    
119
    //create the usrp2 implementation guts
120
    return device::sptr(
121
        new usrp2_impl(ctrl_transport, data_transport)
122
    );
123
}
124

    
125
/***********************************************************************
126
 * Structors
127
 **********************************************************************/
128
usrp2_impl::usrp2_impl(
129
    udp_simple::sptr ctrl_transport,
130
    udp_zero_copy::sptr data_transport
131
){
132
    _data_transport = data_transport;
133

    
134
    //make a new interface for usrp2 stuff
135
    _iface = usrp2_iface::make(ctrl_transport);
136

    
137
    //load the allowed decim/interp rates
138
    //_USRP2_RATES = range(4, 128+1, 1) + range(130, 256+1, 2) + range(260, 512+1, 4)
139
    _allowed_decim_and_interp_rates.clear();
140
    for (size_t i = 4; i <= 128; i+=1){
141
        _allowed_decim_and_interp_rates.push_back(i);
142
    }
143
    for (size_t i = 130; i <= 256; i+=2){
144
        _allowed_decim_and_interp_rates.push_back(i);
145
    }
146
    for (size_t i = 260; i <= 512; i+=4){
147
        _allowed_decim_and_interp_rates.push_back(i);
148
    }
149

    
150
    //init the mboard
151
    mboard_init();
152

    
153
    //init the ddc
154
    init_ddc_config();
155

    
156
    //init the duc
157
    init_duc_config();
158

    
159
    //initialize the clock configuration
160
    init_clock_config();
161

    
162
    //init the tx and rx dboards (do last)
163
    dboard_init();
164

    
165
    //init the send and recv io
166
    io_init();
167

    
168
}
169

    
170
usrp2_impl::~usrp2_impl(void){
171
    /* NOP */
172
}
173

    
174
/***********************************************************************
175
 * Device Properties
176
 **********************************************************************/
177
void usrp2_impl::get(const wax::obj &key_, wax::obj &val){
178
    wax::obj key; std::string name;
179
    boost::tie(key, name) = extract_named_prop(key_);
180

    
181
    //handle the get request conditioned on the key
182
    switch(key.as<device_prop_t>()){
183
    case DEVICE_PROP_NAME:
184
        val = std::string("usrp2 device");
185
        return;
186

    
187
    case DEVICE_PROP_MBOARD:
188
        ASSERT_THROW(name == "");
189
        val = _mboard_proxy->get_link();
190
        return;
191

    
192
    case DEVICE_PROP_MBOARD_NAMES:
193
        val = prop_names_t(1, "");
194
        return;
195

    
196
    case DEVICE_PROP_MAX_RX_SAMPLES:
197
        val = size_t(_max_rx_samples_per_packet);
198
        return;
199

    
200
    case DEVICE_PROP_MAX_TX_SAMPLES:
201
        val = size_t(_max_tx_samples_per_packet);
202
        return;
203

    
204
    }
205
}
206

    
207
void usrp2_impl::set(const wax::obj &, const wax::obj &){
208
    throw std::runtime_error("Cannot set in usrp2 device");
209
}