diff options
author | Josh Blum <josh@joshknows.com> | 2010-02-12 18:07:55 -0800 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2010-02-12 18:07:55 -0800 |
commit | 9fff25f4e5da179ea29ff44278e0415a337870cb (patch) | |
tree | cfbee4cf2921fd4bd415e3af1c1d466f79bab3d7 | |
parent | 350f5c5decca20a54132867283448fd32226bbc2 (diff) | |
download | uhd-9fff25f4e5da179ea29ff44278e0415a337870cb.tar.gz uhd-9fff25f4e5da179ea29ff44278e0415a337870cb.tar.bz2 uhd-9fff25f4e5da179ea29ff44278e0415a337870cb.zip |
Added a templated dictionary class because its more useful than map.
Made the device addrs into a string:string dict.
If its all strings we dont have to change the top level caller for new product.
Created shared_iovec class to manage memory for device recvs.
Work on the bro/dude control protocol for usrp2.
-rw-r--r-- | apps/discover_usrps.cpp | 5 | ||||
-rw-r--r-- | firmware/microblaze/apps/txrx.c | 25 | ||||
-rw-r--r-- | include/uhd/Makefile.am | 2 | ||||
-rw-r--r-- | include/uhd/device.hpp | 7 | ||||
-rw-r--r-- | include/uhd/device_addr.hpp | 72 | ||||
-rw-r--r-- | include/uhd/dict.hpp | 140 | ||||
-rw-r--r-- | include/uhd/shared_iovec.hpp | 54 | ||||
-rw-r--r-- | include/uhd/transport/udp.hpp | 7 | ||||
-rw-r--r-- | include/uhd/usrp/mboard/usrp2.hpp | 5 | ||||
-rw-r--r-- | include/uhd/usrp/usrp.hpp | 6 | ||||
-rw-r--r-- | lib/Makefile.am | 1 | ||||
-rw-r--r-- | lib/device.cpp | 26 | ||||
-rw-r--r-- | lib/device_addr.cpp | 60 | ||||
-rw-r--r-- | lib/shared_iovec.cpp | 28 | ||||
-rw-r--r-- | lib/transport/udp.cpp | 16 | ||||
-rw-r--r-- | lib/usrp/mboard/test.cpp | 4 | ||||
-rw-r--r-- | lib/usrp/mboard/usrp2.cpp | 62 | ||||
-rw-r--r-- | lib/usrp/mboard/usrp2_fw_common.h | 30 | ||||
-rw-r--r-- | lib/usrp/usrp.cpp | 15 | ||||
-rw-r--r-- | test/device_test.cpp | 11 |
20 files changed, 403 insertions, 173 deletions
diff --git a/apps/discover_usrps.cpp b/apps/discover_usrps.cpp index 036d6378a..52eb85b0a 100644 --- a/apps/discover_usrps.cpp +++ b/apps/discover_usrps.cpp @@ -41,9 +41,10 @@ int main(int argc, char *argv[]){ } //extract the ip address (not optional for now) - uhd::device_addr_t device_addr(uhd::DEVICE_ADDR_TYPE_UDP); + uhd::device_addr_t device_addr; + device_addr["type"] = "udp"; if (vm.count("ip-addr")) { - device_addr.udp_args.addr = vm["ip-addr"].as<std::string>(); + device_addr["addr"] = vm["ip-addr"].as<std::string>(); } else { std::cout << "IP Addess was not set" << std::endl; return ~0; diff --git a/firmware/microblaze/apps/txrx.c b/firmware/microblaze/apps/txrx.c index 1c43a2ca1..2cc414f02 100644 --- a/firmware/microblaze/apps/txrx.c +++ b/firmware/microblaze/apps/txrx.c @@ -159,28 +159,37 @@ void handle_udp_ctrl_packet( struct socket_address src, struct socket_address dst, unsigned char *payload, int payload_len ){ - printf("Got ctrl packet #words: %d\n", (int)payload_len); + //printf("Got ctrl packet #words: %d\n", (int)payload_len); if (payload_len < sizeof(usrp2_ctrl_data_t)){ //TODO send err packet return; } + //setup the input and output data usrp2_ctrl_data_t *ctrl_data_in = (usrp2_ctrl_data_t *)payload; usrp2_ctrl_data_t ctrl_data_out = { - .id=USRP2_CTRL_ID_NONE, + .id=USRP2_CTRL_ID_HUH_WHAT, .seq=ctrl_data_in->seq }; + //handle the data based on the id switch(ctrl_data_in->id){ - case USRP2_CTRL_ID_HELLO: - ctrl_data_out.id = ctrl_data_in->id; - //grab the addrs + + case USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO: + ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE; struct ip_addr ip_addr = get_my_ip_addr(); + memcpy(&ctrl_data_out.data.ip_addr, &ip_addr, sizeof(ip_addr)); + break; + + case USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO: + ctrl_data_out.id = USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE; eth_mac_addr_t mac_addr = get_my_eth_mac_addr(); - //copy them into the out data - memcpy(&ctrl_data_out.data.discovery_addrs.ip_addr, &ip_addr, sizeof(ip_addr)); - memcpy(&ctrl_data_out.data.discovery_addrs.mac_addr, &mac_addr, sizeof(mac_addr)); + memcpy(&ctrl_data_out.data.mac_addr, &mac_addr, sizeof(mac_addr)); break; + + default: + ctrl_data_out.id = USRP2_CTRL_ID_HUH_WHAT; + } send_udp_pkt(USRP2_UDP_CTRL_PORT, src, &ctrl_data_out, sizeof(ctrl_data_out)); } diff --git a/include/uhd/Makefile.am b/include/uhd/Makefile.am index 772d1e4b9..6c2034ea8 100644 --- a/include/uhd/Makefile.am +++ b/include/uhd/Makefile.am @@ -23,8 +23,10 @@ this_includedir = $(includedir)/uhd this_include_HEADERS = \ device.hpp \ device_addr.hpp \ + dict.hpp \ gain_handler.hpp \ props.hpp \ + shared_iovec.hpp \ time_spec.hpp \ utils.hpp \ wax.hpp diff --git a/include/uhd/device.hpp b/include/uhd/device.hpp index 09a2bbb2f..dfbfbd7c0 100644 --- a/include/uhd/device.hpp +++ b/include/uhd/device.hpp @@ -25,6 +25,7 @@ #include <boost/shared_ptr.hpp> #include <boost/function.hpp> #include <boost/asio/buffer.hpp> +#include <uhd/shared_iovec.hpp> #include <vector> namespace uhd{ @@ -51,7 +52,7 @@ public: * \param hint a partially (or fully) filled in device address * \return a vector of device addresses for all usrps on the system */ - static std::vector<device_addr_t> discover(const device_addr_t & hint); + static device_addrs_t discover(const device_addr_t &hint); /*! * \brief Create a new usrp device from the device address hint. @@ -64,7 +65,7 @@ public: * \param which which address to use when multiple are discovered * \return a shared pointer to a new device instance */ - static sptr make(const device_addr_t & hint, size_t which = 0); + static sptr make(const device_addr_t &hint, size_t which = 0); /*! * Get the device address for this board. @@ -73,7 +74,7 @@ public: //the io interface virtual void send_raw(const std::vector<boost::asio::const_buffer> &) = 0; - virtual boost::asio::const_buffer recv_raw(void) = 0; + virtual uhd::shared_iovec recv_raw(void) = 0; }; } //namespace uhd diff --git a/include/uhd/device_addr.hpp b/include/uhd/device_addr.hpp index 84ae60881..8ea580321 100644 --- a/include/uhd/device_addr.hpp +++ b/include/uhd/device_addr.hpp @@ -18,10 +18,12 @@ #ifndef INCLUDED_UHD_DEVICE_ADDR_HPP #define INCLUDED_UHD_DEVICE_ADDR_HPP +#include <uhd/dict.hpp> #include <string> #include <iostream> #include <netinet/ether.h> #include <stdint.h> +#include <vector> namespace uhd{ @@ -36,62 +38,30 @@ namespace uhd{ }; /*! - * Possible usrp device interface types. - */ - enum device_addr_type_t{ - DEVICE_ADDR_TYPE_AUTO, - DEVICE_ADDR_TYPE_VIRTUAL, - DEVICE_ADDR_TYPE_USB, - DEVICE_ADDR_TYPE_ETH, - DEVICE_ADDR_TYPE_UDP, - DEVICE_ADDR_TYPE_GPMC - }; + * The device address args are just a mapping of key/value string pairs. + * When left empty, the discovery routine will try to find all usrps. + * The discovery can be narrowed down by specifying the transport type arguments. + * + * For example, to access a specific usrp2 one would specify the transport type + * ("type", "udp") and the transport args ("addr", "<resolvable_hostname_or_addr>"). + */ + typedef dict<std::string, std::string> device_addr_t; + typedef std::vector<device_addr_t> device_addrs_t; /*! - * Structure to hold properties that identify a usrp device. - */ - struct device_addr_t{ - device_addr_type_t type; - struct{ - size_t num_rx_dsps; - size_t num_tx_dsps; - size_t num_dboards; - } virtual_args; - struct{ - uint16_t vendor_id; - uint16_t product_id; - } usb_args; - struct{ - std::string ifc; - std::string mac_addr; - } eth_args; - struct{ - std::string addr; - } udp_args; - struct{ - //TODO unknown for now - } gpmc_args; - - //the discovery args are filled in by the discovery routine - struct{ - uint16_t mboard_id; - } discovery_args; - - /*! - * \brief Convert a usrp device_addr_t into a string representation - */ - std::string to_string(void) const; - - /*! - * \brief Default constructor to initialize the device_addr_t struct - */ - device_addr_t(device_addr_type_t device_addr_type = DEVICE_ADDR_TYPE_AUTO); - }; + * Function to turn a device address into a string. + * Just having the operator<< below should be sufficient. + * However, boost format seems to complain with the % + * and this is just easier because it works. + * \param device_addr a device address instance + * \return the string representation + */ + std::string device_addr_to_string(const device_addr_t &device_addr); } //namespace uhd //ability to use types with stream operators -std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &x); -std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x); +std::ostream& operator<<(std::ostream &, const uhd::device_addr_t &); +std::ostream& operator<<(std::ostream &, const uhd::mac_addr_t &); #endif /* INCLUDED_UHD_DEVICE_ADDR_HPP */ diff --git a/include/uhd/dict.hpp b/include/uhd/dict.hpp new file mode 100644 index 000000000..3abc4273c --- /dev/null +++ b/include/uhd/dict.hpp @@ -0,0 +1,140 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_DICT_HPP +#define INCLUDED_UHD_DICT_HPP + +#include <map> +#include <vector> +#include <boost/foreach.hpp> +#include <stdexcept> + +namespace uhd{ + + /*! + * A templated dictionary class with a python-like interface. + * Its wraps around a std::map internally. + */ + template <class Key, class Val> class dict{ + public: + /*! + * Create a new empty dictionary. + */ + dict(void){ + /* NOP */ + } + + /*! + * Create a dictionary from a map. + * \param map a map with key value pairs + */ + dict(const std::map<Key, Val> &map){ + _map = map; + } + + /*! + * Destroy this dict. + */ + ~dict(void){ + /* NOP */ + } + + /*! + * Get a list of the keys in this dict. + * \return vector of keys + */ + std::vector<Key> get_keys(void) const{ + std::vector<Key> keys; + std::pair<Key, Val> p; + BOOST_FOREACH(p, _map){ + keys.push_back(p.first); + } + return keys; + } + + /*! + * Get a list of the values in this dict. + * \return vector of values + */ + std::vector<Val> get_vals(void) const{ + std::vector<Val> vals; + std::pair<Key, Val> p; + BOOST_FOREACH(p, _map){ + vals.push_back(p.second); + } + return vals; + } + + /*! + * Does the dictionary contain this key? + * \param key the key to look for + * \return true if found + */ + bool has_key(const Key &key) const{ + std::pair<Key, Val> p; + BOOST_FOREACH(p, _map){ + if (p.first == key) return true; + } + return false; + } + + /*! + * Get a value for the given key if it exists. + * If the key is not found throw an error. + * \param key the key to look for + * \return the value at the key + * \throw an exception when not found + */ + const Val &operator[](const Key &key) const{ + if (has_key(key)){ + return _map.find(key)->second; + } + throw std::invalid_argument("key not found in dict"); + } + + /*! + * Set a value for the given key, however, in reality + * it really returns a reference which can be assigned to. + * \param key the key to set to + * \return a reference to the value + */ + Val &operator[](const Key &key){ + return _map[key]; + } + + /*! + * Pop an item out of the dictionary. + * \param key the item key + * \return the value of the item + * \throw an exception when not found + */ + Val pop_key(const Key &key){ + if (has_key(key)){ + Val val = _map.find(key)->second; + _map.erase(key); + return val; + } + throw std::invalid_argument("key not found in dict"); + } + + private: + std::map<Key, Val> _map; //private container + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_DICT_HPP */ diff --git a/include/uhd/shared_iovec.hpp b/include/uhd/shared_iovec.hpp new file mode 100644 index 000000000..a120e55d5 --- /dev/null +++ b/include/uhd/shared_iovec.hpp @@ -0,0 +1,54 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_SHARED_IOVEC_HPP +#define INCLUDED_UHD_SHARED_IOVEC_HPP + +#include <boost/shared_array.hpp> +#include <stdint.h> + +namespace uhd{ + +/*! + * A shared iovec contains a shared array and its length. + * Creating a new shared iovec allocates new memory. + * This memory is freed when all copies are destroyed. + */ +class shared_iovec{ +public: + /*! + * Create a shared iovec and allocate memory. + * \param len the length in bytes + */ + shared_iovec(size_t len=0); + + /*! + * Destroy a shared iovec. + * Will not free the memory unless this is the last copy. + */ + ~shared_iovec(void); + + void *base; + size_t len; + +private: + boost::shared_array<uint8_t> _shared_array; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_SHARED_IOVEC_HPP */ diff --git a/include/uhd/transport/udp.hpp b/include/uhd/transport/udp.hpp index c9a9dd53b..6db6bd377 100644 --- a/include/uhd/transport/udp.hpp +++ b/include/uhd/transport/udp.hpp @@ -18,7 +18,7 @@ #include <boost/asio.hpp> #include <boost/utility.hpp> #include <boost/shared_ptr.hpp> -#include <stdio.h> +#include <uhd/shared_iovec.hpp> #ifndef INCLUDED_UHD_TRANSPORT_UDP_HPP #define INCLUDED_UHD_TRANSPORT_UDP_HPP @@ -59,16 +59,15 @@ public: /*! * Receive a buffer. The memory is managed internally. * Calling recv will invalidate the buffer of the previous recv. - * \return an asio const buffer with internal memory + * \return a shared iovec with allocated memory */ - boost::asio::const_buffer recv(void); + uhd::shared_iovec recv(void); private: boost::asio::ip::udp::socket *_socket; boost::asio::ip::udp::endpoint _receiver_endpoint; boost::asio::ip::udp::endpoint _sender_endpoint; boost::asio::io_service _io_service; - uint8_t _recv_buff[1500]; //max mtu }; }} //namespace diff --git a/include/uhd/usrp/mboard/usrp2.hpp b/include/uhd/usrp/mboard/usrp2.hpp index 8c2430dbd..4950f4cd1 100644 --- a/include/uhd/usrp/mboard/usrp2.hpp +++ b/include/uhd/usrp/mboard/usrp2.hpp @@ -21,6 +21,7 @@ #include <uhd/usrp/mboard/base.hpp> #include <uhd/device_addr.hpp> #include <uhd/usrp/dboard/manager.hpp> +#include <uhd/transport/udp.hpp> #include <map> namespace uhd{ namespace usrp{ namespace mboard{ @@ -36,7 +37,7 @@ public: * \param hint a device addr with the usrp2 address filled in * \return a vector of device addresses for all usrp2s found */ - static std::vector<device_addr_t> discover(const device_addr_t &hint); + static device_addrs_t discover(const device_addr_t &hint); usrp2(const device_addr_t &); ~usrp2(void); @@ -46,6 +47,8 @@ private: void set(const wax::obj &, const wax::obj &); std::map<std::string, dboard::manager::sptr> _dboard_managers; + uhd::transport::udp::sptr _udp_ctrl_transport; + uhd::transport::udp::sptr _udp_data_transport; }; }}} //namespace diff --git a/include/uhd/usrp/usrp.hpp b/include/uhd/usrp/usrp.hpp index 975debed1..0dca36f62 100644 --- a/include/uhd/usrp/usrp.hpp +++ b/include/uhd/usrp/usrp.hpp @@ -32,12 +32,12 @@ namespace uhd{ namespace usrp{ */ class usrp : public device{ public: - usrp(const device_addr_t & device_addr); + usrp(const device_addr_t &device_addr); ~usrp(void); //the io interface void send_raw(const std::vector<boost::asio::const_buffer> &); - boost::asio::const_buffer recv_raw(void); + uhd::shared_iovec recv_raw(void); private: void get(const wax::obj &, wax::obj &); @@ -45,7 +45,7 @@ private: std::map<std::string, mboard::base::sptr> _mboards; boost::function<void(const std::vector<boost::asio::const_buffer> &)> _send_raw_cb; - boost::function<boost::asio::const_buffer(void)> _recv_raw_cb; + boost::function<uhd::shared_iovec(void)> _recv_raw_cb; }; }} //namespace diff --git a/lib/Makefile.am b/lib/Makefile.am index ff7c6b75d..58e43b8b2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -27,6 +27,7 @@ libuhd_la_SOURCES = \ device.cpp \ device_addr.cpp \ gain_handler.cpp \ + shared_iovec.cpp \ uhd.cpp \ wax.cpp diff --git a/lib/device.cpp b/lib/device.cpp index 4b51a70d4..822733217 100644 --- a/lib/device.cpp +++ b/lib/device.cpp @@ -23,35 +23,37 @@ using namespace uhd; -std::vector<device_addr_t> device::discover(const device_addr_t & hint = device_addr_t()){ - std::vector<device_addr_t> device_addrs; - if (hint.type == DEVICE_ADDR_TYPE_UDP){ +device_addrs_t device::discover(const device_addr_t &hint){ + device_addrs_t device_addrs; + if (not hint.has_key("type")){ + //TODO nothing + } + else if (hint["type"] == "test"){ + //make a copy of the hint for testing + device_addr_t test_device_addr = hint; + device_addrs.push_back(test_device_addr); + } + else if (hint["type"] == "udp"){ std::vector<device_addr_t> usrp2_addrs = usrp::mboard::usrp2::discover(hint); device_addrs.insert(device_addrs.begin(), usrp2_addrs.begin(), usrp2_addrs.end()); } - if (hint.type == DEVICE_ADDR_TYPE_VIRTUAL){ - //make a copy of the hint for virtual testing - device_addr_t virtual_device_addr = hint; - device_addrs.push_back(virtual_device_addr); - } return device_addrs; } -device::sptr device::make(const device_addr_t & hint, size_t which){ +device::sptr device::make(const device_addr_t &hint, size_t which){ std::vector<device_addr_t> device_addrs = discover(hint); //check that we found any devices if (device_addrs.size() == 0){ throw std::runtime_error(str( - boost::format("No devices found for %s") % hint.to_string() + boost::format("No devices found for %s") % device_addr_to_string(hint) )); } //check that the which index is valid if (device_addrs.size() <= which){ throw std::runtime_error(str( - boost::format("No device at index %d for %s") - % which % hint.to_string() + boost::format("No device at index %d for %s") % which % device_addr_to_string(hint) )); } diff --git a/lib/device_addr.cpp b/lib/device_addr.cpp index ee6dbbbc8..ffd511f92 100644 --- a/lib/device_addr.cpp +++ b/lib/device_addr.cpp @@ -21,6 +21,7 @@ #include <stdexcept> #include <boost/format.hpp> #include <boost/algorithm/string.hpp> +#include <boost/foreach.hpp> //----------------------- u2 mac addr wrapper ------------------------// uhd::mac_addr_t::mac_addr_t(const std::string &mac_addr_str_){ @@ -71,58 +72,15 @@ std::ostream& operator<<(std::ostream &os, const uhd::mac_addr_t &x){ } //----------------------- usrp device_addr_t wrapper -------------------------// -uhd::device_addr_t::device_addr_t(device_addr_type_t device_addr_type){ - type = device_addr_type; - virtual_args.num_rx_dsps = 0; - virtual_args.num_tx_dsps = 0; - virtual_args.num_dboards = 0; - usb_args.vendor_id = 0xffff; - usb_args.product_id = 0xffff; - eth_args.ifc = "eth0"; - eth_args.mac_addr = ""; - udp_args.addr = ""; - discovery_args.mboard_id = ~0; -} - -std::string uhd::device_addr_t::to_string(void) const{ - std::ostringstream out; - out << "USRP Type: "; - switch(type){ - case DEVICE_ADDR_TYPE_AUTO: - out << "Automatic" << std::endl; - break; - case DEVICE_ADDR_TYPE_VIRTUAL: - out << "Virtual" << std::endl; - out << "Num RX DSPs: " << virtual_args.num_rx_dsps << std::endl; - out << "Num TX DSPs: " << virtual_args.num_rx_dsps << std::endl; - out << "Num dboards: " << virtual_args.num_dboards << std::endl; - break; - case DEVICE_ADDR_TYPE_USB: - out << "USB Port" << std::endl; - out << "Vendor ID: 0x" << std::hex << usb_args.vendor_id << std::endl; - out << "Product ID: 0x" << std::hex << usb_args.product_id << std::endl; - break; - case DEVICE_ADDR_TYPE_ETH: - out << "Raw Ethernet" << std::endl; - out << "Interface: " << eth_args.ifc << std::endl; - out << "MAC Addr: " << eth_args.mac_addr << std::endl; - break; - case DEVICE_ADDR_TYPE_UDP: - out << "UDP Socket" << std::endl; - out << "Address: " << udp_args.addr << std::endl; - break; - case DEVICE_ADDR_TYPE_GPMC: - out << "GPMC" << std::endl; - break; - default: - out << "Unknown" << std::endl; +std::string uhd::device_addr_to_string(const uhd::device_addr_t &device_addr){ + std::stringstream ss; + BOOST_FOREACH(std::string key, device_addr.get_keys()){ + ss << boost::format("%s: %s") % key % device_addr[key] << std::endl; } - out << std::endl; - return out.str(); + return ss.str(); } -std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &x) -{ - os << x.to_string(); - return os; +std::ostream& operator<<(std::ostream &os, const uhd::device_addr_t &device_addr){ + os << uhd::device_addr_to_string(device_addr); + return os; } diff --git a/lib/shared_iovec.cpp b/lib/shared_iovec.cpp new file mode 100644 index 000000000..60062fbf0 --- /dev/null +++ b/lib/shared_iovec.cpp @@ -0,0 +1,28 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/shared_iovec.hpp> + +uhd::shared_iovec::shared_iovec(size_t len_){ + _shared_array = boost::shared_array<uint8_t>(new uint8_t[len_]); + base = _shared_array.get(); + len = len_; +} + +uhd::shared_iovec::~shared_iovec(void){ + /* NOP */ +} diff --git a/lib/transport/udp.cpp b/lib/transport/udp.cpp index f42ddcb75..06defb107 100644 --- a/lib/transport/udp.cpp +++ b/lib/transport/udp.cpp @@ -53,15 +53,15 @@ void uhd::transport::udp::send(const boost::asio::const_buffer &buff){ send(buffs); } -boost::asio::const_buffer uhd::transport::udp::recv(void){ - size_t len = 0; - //recv if data is available - if (_socket->available()){ - len = _socket->receive_from( - boost::asio::buffer(_recv_buff, sizeof(_recv_buff)), +uhd::shared_iovec uhd::transport::udp::recv(void){ + //allocate a buffer for the number of bytes available (could be zero) + uhd::shared_iovec iov(_socket->available()); + //call recv only if data is available + if (iov.len != 0){ + _socket->receive_from( + boost::asio::buffer(iov.base, iov.len), _sender_endpoint ); } - //return the buffer with the received length - return boost::asio::buffer(_recv_buff, len); + return iov; } diff --git a/lib/usrp/mboard/test.cpp b/lib/usrp/mboard/test.cpp index 9ad11c046..b4ac66eb7 100644 --- a/lib/usrp/mboard/test.cpp +++ b/lib/usrp/mboard/test.cpp @@ -109,8 +109,10 @@ private: * test usrp mboard class **********************************************************************/ test::test(const device_addr_t &device_addr){ + //extract the number of dboards + size_t num_dboards = boost::lexical_cast<size_t>(device_addr["num_dboards"]); //create a manager for each dboard - for (size_t i = 0; i < device_addr.virtual_args.num_dboards; i++){ + for (size_t i = 0; i < num_dboards; i++){ dboard::interface::sptr ifc(new dummy_interface()); _dboard_managers[boost::lexical_cast<std::string>(i)] = dboard::manager::sptr( new dboard::manager(dboard::ID_BASIC_RX, dboard::ID_BASIC_TX, ifc) diff --git a/lib/usrp/mboard/usrp2.cpp b/lib/usrp/mboard/usrp2.cpp index 9282a541a..9de478672 100644 --- a/lib/usrp/mboard/usrp2.cpp +++ b/lib/usrp/mboard/usrp2.cpp @@ -16,7 +16,6 @@ // #include <uhd/usrp/mboard/usrp2.hpp> -#include <uhd/transport/udp.hpp> #include "usrp2_fw_common.h" #include <uhd/device.hpp> #include <boost/thread.hpp> @@ -29,35 +28,40 @@ using namespace uhd::usrp::mboard; /*********************************************************************** * Discovery over the udp transport **********************************************************************/ -std::vector<uhd::device_addr_t> usrp2::discover(const device_addr_t &hint){ - std::vector<uhd::device_addr_t> usrp2_addrs; +uhd::device_addrs_t usrp2::discover(const device_addr_t &hint){ + device_addrs_t usrp2_addrs; //create a udp transport to communicate + //TODO if an addr is not provided, search all interfaces? std::string ctrl_port = boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT); - uhd::transport::udp udp_transport(hint.udp_args.addr, ctrl_port, true); + uhd::transport::udp udp_transport(hint["addr"], ctrl_port, true); //send a hello control packet usrp2_ctrl_data_t ctrl_data_out; - ctrl_data_out.id = htonl(USRP2_CTRL_ID_HELLO); + ctrl_data_out.id = htonl(USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO); udp_transport.send(boost::asio::buffer(&ctrl_data_out, sizeof(ctrl_data_out))); //loop and recieve until the time is up size_t num_timeouts = 0; while(true){ - boost::asio::const_buffer buff = udp_transport.recv(); + uhd::shared_iovec iov = udp_transport.recv(); //std::cout << boost::asio::buffer_size(buff) << "\n"; - if (boost::asio::buffer_size(buff) < sizeof(usrp2_ctrl_data_t)){ + if (iov.len < sizeof(usrp2_ctrl_data_t)){ //sleep a little so we dont burn cpu if (num_timeouts++ > 50) break; boost::this_thread::sleep(boost::posix_time::milliseconds(1)); }else{ //handle the received data - const usrp2_ctrl_data_t *ctrl_data_in = boost::asio::buffer_cast<const usrp2_ctrl_data_t *>(buff); + const usrp2_ctrl_data_t *ctrl_data_in = reinterpret_cast<const usrp2_ctrl_data_t *>(iov.base); switch(ntohl(ctrl_data_in->id)){ - case USRP2_CTRL_ID_HELLO: + case USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE: //make a boost asio ipv4 with the raw addr in host byte order - boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.discovery_addrs.ip_addr)); - std::cout << "hello " << ip_addr.to_string() << "\n"; + boost::asio::ip::address_v4 ip_addr(ntohl(ctrl_data_in->data.ip_addr)); + device_addr_t new_addr; + new_addr["name"] = "USRP2"; + new_addr["type"] = "udp"; + new_addr["addr"] = ip_addr.to_string(); + usrp2_addrs.push_back(new_addr); break; } } @@ -65,3 +69,39 @@ std::vector<uhd::device_addr_t> usrp2::discover(const device_addr_t &hint){ return usrp2_addrs; } + +/*********************************************************************** + * Structors + **********************************************************************/ +usrp2::usrp2(const device_addr_t &device_addr){ + _udp_ctrl_transport = uhd::transport::udp::sptr( + new uhd::transport::udp( + device_addr["addr"], + boost::lexical_cast<std::string>(USRP2_UDP_CTRL_PORT) + ) + ); + _udp_data_transport = uhd::transport::udp::sptr( + new uhd::transport::udp( + device_addr["addr"], + boost::lexical_cast<std::string>(USRP2_UDP_DATA_PORT) + ) + ); +} + +usrp2::~usrp2(void){ + /* NOP */ +} + +/*********************************************************************** + * Get Properties + **********************************************************************/ +void usrp2::get(const wax::obj &, wax::obj &){ + +} + +/*********************************************************************** + * Set Properties + **********************************************************************/ +void usrp2::set(const wax::obj &, const wax::obj &){ + +} diff --git a/lib/usrp/mboard/usrp2_fw_common.h b/lib/usrp/mboard/usrp2_fw_common.h index 217d8cf1c..4ea9d5467 100644 --- a/lib/usrp/mboard/usrp2_fw_common.h +++ b/lib/usrp/mboard/usrp2_fw_common.h @@ -28,24 +28,38 @@ extern "C" { #endif // udp ports for the usrp2 communication -// Dynamic and/or private ports: 49152–65535 +// Dynamic and/or private ports: 49152-65535 #define USRP2_UDP_CTRL_PORT 49152 #define USRP2_UDP_DATA_PORT 49153 typedef enum{ - USRP2_CTRL_ID_NONE, - USRP2_CTRL_ID_HELLO + USRP2_CTRL_ID_HUH_WHAT, + //USRP2_CTRL_ID_FOR_SURE, //TODO error condition enums + //USRP2_CTRL_ID_SUX_MAN, + USRP2_CTRL_ID_GIVE_ME_YOUR_IP_ADDR_BRO, + USRP2_CTRL_ID_THIS_IS_MY_IP_ADDR_DUDE, + USRP2_CTRL_ID_HERE_IS_A_NEW_IP_ADDR_BRO, + USRP2_CTRL_ID_GIVE_ME_YOUR_MAC_ADDR_BRO, + USRP2_CTRL_ID_THIS_IS_MY_MAC_ADDR_DUDE, + USRP2_CTRL_ID_HERE_IS_A_NEW_MAC_ADDR_BRO } usrp2_ctrl_id_t; typedef struct{ uint32_t id; uint32_t seq; union{ - struct{ - uint32_t ip_addr; - uint8_t mac_addr[6]; - uint8_t _padding[2]; - } discovery_addrs; + uint32_t ip_addr; + uint8_t mac_addr[6]; + /*struct { + uint8_t bank; + uint16_t ddr; + uint16_t mask; + } gpio_ddr_args; + struct { + uint8_t bank; + uint16_t val; + uint16_t mask; + } gpio_val_args;*/ } data; } usrp2_ctrl_data_t; diff --git a/lib/usrp/usrp.cpp b/lib/usrp/usrp.cpp index c49a63d49..68b423538 100644 --- a/lib/usrp/usrp.cpp +++ b/lib/usrp/usrp.cpp @@ -16,6 +16,7 @@ // #include <uhd/usrp/usrp.hpp> +#include <uhd/usrp/mboard/usrp2.hpp> #include <uhd/usrp/mboard/test.hpp> #include <uhd/utils.hpp> #include <boost/format.hpp> @@ -32,22 +33,28 @@ static void send_raw_default(const std::vector<boost::asio::const_buffer> &){ throw std::runtime_error("No callback registered for send raw"); } -static boost::asio::const_buffer recv_raw_default(void){ +static uhd::shared_iovec recv_raw_default(void){ throw std::runtime_error("No callback registered for recv raw"); } /*********************************************************************** * the usrp device wrapper **********************************************************************/ -usrp::usrp(const device_addr_t & device_addr){ +usrp::usrp(const device_addr_t &device_addr){ //set the default callbacks, the code below should replace them _send_raw_cb = boost::bind(&send_raw_default, _1); _recv_raw_cb = boost::bind(&recv_raw_default); //create mboard based on the device addr - if (device_addr.type == DEVICE_ADDR_TYPE_VIRTUAL){ + if (not device_addr.has_key("type")){ + //TODO nothing + } + else if (device_addr["type"] == "test"){ _mboards[""] = mboard::base::sptr(new mboard::test(device_addr)); } + else if (device_addr["type"] == "udp"){ + _mboards[""] = mboard::base::sptr(new mboard::usrp2(device_addr)); + } } usrp::~usrp(void){ @@ -87,6 +94,6 @@ void usrp::send_raw(const std::vector<boost::asio::const_buffer> &buffs){ return _send_raw_cb(buffs); } -boost::asio::const_buffer usrp::recv_raw(void){ +uhd::shared_iovec usrp::recv_raw(void){ return _recv_raw_cb(); } diff --git a/test/device_test.cpp b/test/device_test.cpp index a868cf9f6..6373ff41b 100644 --- a/test/device_test.cpp +++ b/test/device_test.cpp @@ -21,10 +21,9 @@ using namespace uhd; BOOST_AUTO_TEST_CASE(test_device){ - device_addr_t device_addr(DEVICE_ADDR_TYPE_VIRTUAL); - device_addr.virtual_args.num_dboards = 2; - device_addr.virtual_args.num_rx_dsps = 3; - device_addr.virtual_args.num_tx_dsps = 4; + device_addr_t device_addr; + device_addr["type"] = "test"; + device_addr["num_dboards"] = "2"; device::sptr dev = device::make(device_addr); std::cout << "Access the device" << std::endl; @@ -34,11 +33,11 @@ BOOST_AUTO_TEST_CASE(test_device){ wax::obj mb0 = (*dev)[DEVICE_PROP_MBOARD]; std::cout << wax::cast<std::string>(mb0[MBOARD_PROP_NAME]) << std::endl; BOOST_CHECK_EQUAL( - device_addr.virtual_args.num_dboards, + 2, wax::cast<prop_names_t>(mb0[MBOARD_PROP_RX_DBOARD_NAMES]).size() ); BOOST_CHECK_EQUAL( - device_addr.virtual_args.num_dboards, + 2, wax::cast<prop_names_t>(mb0[MBOARD_PROP_TX_DBOARD_NAMES]).size() ); |