Statistics
| Branch: | Tag: | Revision:

root / host / lib / usrp / usrp_e100 / usrp_e100_impl.cpp @ 30996463

History | View | Annotate | Download (7.11 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 "usrp_e100_impl.hpp"
19
#include "usrp_e100_regs.hpp"
20
#include <uhd/usrp/device_props.hpp>
21
#include <uhd/usrp/mboard_props.hpp>
22
#include <uhd/utils/assert.hpp>
23
#include <uhd/utils/static.hpp>
24
#include <uhd/utils/images.hpp>
25
#include <uhd/utils/warning.hpp>
26
#include <boost/format.hpp>
27
#include <boost/filesystem.hpp>
28
#include <boost/functional/hash.hpp>
29
#include <iostream>
30
#include <fstream>
31

    
32
using namespace uhd;
33
using namespace uhd::usrp;
34
namespace fs = boost::filesystem;
35

    
36
/***********************************************************************
37
 * Discovery
38
 **********************************************************************/
39
static device_addrs_t usrp_e100_find(const device_addr_t &hint){
40
    device_addrs_t usrp_e100_addrs;
41

    
42
    //return an empty list of addresses when type is set to non-usrp-e
43
    if (hint.has_key("type") and hint["type"] != "usrp-e") return usrp_e100_addrs;
44

    
45
    //device node not provided, assume its 0
46
    if (not hint.has_key("node")){
47
        device_addr_t new_addr = hint;
48
        new_addr["node"] = "/dev/usrp_e0";
49
        return usrp_e100_find(new_addr);
50
    }
51

    
52
    //use the given device node name
53
    if (fs::exists(hint["node"])){
54
        device_addr_t new_addr;
55
        new_addr["type"] = "usrp-e";
56
        new_addr["node"] = fs::system_complete(fs::path(hint["node"])).file_string();
57
        try{
58
            usrp_e100_iface::sptr iface = usrp_e100_iface::make(new_addr["node"]);
59
            new_addr["name"] = iface->mb_eeprom["name"];
60
            new_addr["serial"] = iface->mb_eeprom["serial"];
61
            if (
62
                (not hint.has_key("name")   or hint["name"]   == new_addr["name"]) and
63
                (not hint.has_key("serial") or hint["serial"] == new_addr["serial"])
64
            ){
65
                usrp_e100_addrs.push_back(new_addr);
66
            }
67
        }
68
        catch(const std::exception &e){
69
            uhd::warning::post(
70
                std::string("Ignoring discovered device\n")
71
                + e.what()
72
            );
73
        }
74
    }
75

    
76
    return usrp_e100_addrs;
77
}
78

    
79
/***********************************************************************
80
 * Make
81
 **********************************************************************/
82
static device::sptr usrp_e100_make(const device_addr_t &device_addr){
83

    
84
    //setup the main interface into fpga
85
    std::string node = device_addr["node"];
86
    std::cout << boost::format("Opening USRP-E on %s") % node << std::endl;
87
    usrp_e100_iface::sptr iface = usrp_e100_iface::make(node);
88

    
89
    //------------------------------------------------------------------
90
    //-- Handle the FPGA loading...
91
    //-- The image can be confimed as already loaded when:
92
    //--   1) The compatibility number matches.
93
    //--   2) The hash in the hash-file matches.
94
    //------------------------------------------------------------------
95
    static const char *hash_file_path = "/tmp/usrp_e100_hash";
96

    
97
    //extract the fpga path for usrp-e
98
    std::string usrp_e100_fpga_image = find_image_path(
99
        device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin"
100
    );
101

    
102
    //calculate a hash of the fpga file
103
    size_t fpga_hash = 0;
104
    {
105
        std::ifstream file(usrp_e100_fpga_image.c_str());
106
        if (not file.good()) throw std::runtime_error(
107
            "cannot open fpga file for read: " + usrp_e100_fpga_image
108
        );
109
        do{
110
            boost::hash_combine(fpga_hash, file.get());
111
        } while (file.good());
112
        file.close();
113
    }
114

    
115
    //read the compatibility number
116
    boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
117

    
118
    //read the hash in the hash-file
119
    size_t loaded_hash = 0;
120
    try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){}
121

    
122
    //if not loaded: load the fpga image and write the hash-file
123
    if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){
124
        iface.reset();
125
        usrp_e100_load_fpga(usrp_e100_fpga_image);
126
        std::cout << boost::format("re-Opening USRP-E on %s") % node << std::endl;
127
        iface = usrp_e100_iface::make(node);
128
        try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){}
129
    }
130

    
131
    //check that the compatibility is correct
132
    fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT);
133
    if (fpga_compat_num != USRP_E_COMPAT_NUM){
134
        throw std::runtime_error(str(boost::format(
135
            "Expected fpga compatibility number 0x%x, but got 0x%x:\n"
136
            "The fpga build is not compatible with the host code build."
137
        ) % USRP_E_COMPAT_NUM % fpga_compat_num));
138
    }
139

    
140
    return device::sptr(new usrp_e100_impl(iface));
141
}
142

    
143
UHD_STATIC_BLOCK(register_usrp_e100_device){
144
    device::register_device(&usrp_e100_find, &usrp_e100_make);
145
}
146

    
147
/***********************************************************************
148
 * Structors
149
 **********************************************************************/
150
usrp_e100_impl::usrp_e100_impl(usrp_e100_iface::sptr iface): _iface(iface){
151

    
152
    //setup interfaces into hardware
153
    _clock_ctrl = usrp_e100_clock_ctrl::make(_iface);
154
    _codec_ctrl = usrp_e100_codec_ctrl::make(_iface);
155

    
156
    //initialize the mboard
157
    mboard_init();
158

    
159
    //initialize the dboards
160
    dboard_init();
161

    
162
    //initialize the dsps
163
    rx_ddc_init();
164
    tx_duc_init();
165

    
166
    //init the codec properties
167
    codec_init();
168

    
169
    //init the io send/recv
170
    io_init();
171

    
172
    //set default subdev specs
173
    this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t());
174
    this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t());
175
}
176

    
177
usrp_e100_impl::~usrp_e100_impl(void){
178
    /* NOP */
179
}
180

    
181
/***********************************************************************
182
 * Device Get
183
 **********************************************************************/
184
void usrp_e100_impl::get(const wax::obj &key_, wax::obj &val){
185
    named_prop_t key = named_prop_t::extract(key_);
186

    
187
    //handle the get request conditioned on the key
188
    switch(key.as<device_prop_t>()){
189
    case DEVICE_PROP_NAME:
190
        val = std::string("usrp-e device");
191
        return;
192

    
193
    case DEVICE_PROP_MBOARD:
194
        UHD_ASSERT_THROW(key.name == "");
195
        val = _mboard_proxy->get_link();
196
        return;
197

    
198
    case DEVICE_PROP_MBOARD_NAMES:
199
        val = prop_names_t(1, ""); //vector of size 1 with empty string
200
        return;
201

    
202
    default: UHD_THROW_PROP_GET_ERROR();
203
    }
204
}
205

    
206
/***********************************************************************
207
 * Device Set
208
 **********************************************************************/
209
void usrp_e100_impl::set(const wax::obj &, const wax::obj &){
210
    UHD_THROW_PROP_SET_ERROR();
211
}