aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mpm/CMakeLists.txt28
-rw-r--r--mpm/dboards/magnesium_manager.hpp10
-rw-r--r--mpm/include/lmk/lmk04828_spi_iface.hpp13
-rw-r--r--mpm/include/mpm/spi/spidev_iface.hpp33
-rw-r--r--mpm/lib/CMakeLists.txt6
-rw-r--r--mpm/lib/lmk04828/CMakeLists.txt4
-rw-r--r--mpm/lib/mykonos/ad937x_ctrl.hpp29
-rw-r--r--mpm/lib/net_helper.cpp118
-rw-r--r--mpm/lib/net_helper.hpp69
-rw-r--r--mpm/lib/udev_helper.cpp93
-rw-r--r--mpm/lib/udev_helper.hpp62
-rw-r--r--mpm/lib/xbar_iface.cpp56
-rw-r--r--mpm/lib/xbar_iface.hpp69
-rw-r--r--mpm/python/CMakeLists.txt19
-rw-r--r--mpm/python/converters.hpp105
-rw-r--r--mpm/python/copy_python_module.cmake4
-rw-r--r--mpm/python/lib_helper.cpp38
-rw-r--r--mpm/python/lib_periphs.cpp49
-rw-r--r--mpm/python/lib_periphs.hpp4
-rw-r--r--mpm/python/n310_periphs.cpp21
-rw-r--r--mpm/python/n310_periphs.hpp3
-rw-r--r--mpm/python/pyusrp_periphs.cpp53
-rwxr-xr-xmpm/python/setup.py.in2
-rw-r--r--mpm/python/tests_periphs.cpp19
-rw-r--r--mpm/python/tests_periphs.hpp17
-rw-r--r--mpm/python/usrp_mpm/CMakeLists.txt2
-rw-r--r--mpm/python/usrp_mpm/__init__.py2
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/__init__.py28
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/base.py37
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/eiscat.py31
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/magnesium.py50
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/unknown.py32
-rw-r--r--mpm/python/usrp_mpm/helper.py3
-rw-r--r--mpm/python/usrp_mpm/periph_manager/__init__.py29
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py75
-rw-r--r--mpm/python/usrp_mpm/periph_manager/n310.py46
-rw-r--r--mpm/python/usrp_mpm/periphs.py47
-rw-r--r--mpm/python/usrp_mpm/rpc_server.py5
-rw-r--r--mpm/python/usrp_mpm/types.py31
39 files changed, 1190 insertions, 152 deletions
diff --git a/mpm/CMakeLists.txt b/mpm/CMakeLists.txt
index 73ec07657..0de4ad262 100644
--- a/mpm/CMakeLists.txt
+++ b/mpm/CMakeLists.txt
@@ -61,12 +61,25 @@ FIND_PACKAGE(Boost 1.53 COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
+message("python executable: ${PYTHON_EXECUTABLE}")
MESSAGE(STATUS "Boost include directories: ${Boost_INCLUDE_DIRS}")
MESSAGE(STATUS "Boost library directories: ${Boost_LIBRARY_DIRS}")
MESSAGE(STATUS "Boost libraries: ${Boost_LIBRARIES}")
########################################################################
+# Setup Python API
+########################################################################
+
+SET(PYTHON_ADDITIONAL_VERSIONS 2.7 3.4 3.5)
+message("python executable: ${PYTHON_EXECUTABLE}")
+FIND_PACKAGE(PythonInterp)
+message("python executable: ${PYTHON_EXECUTABLE}")
+FIND_PACKAGE(PythonLibs)
+message("python executable: ${PYTHON_EXECUTABLE}")
+
+
+########################################################################
# Setup library configuration
########################################################################
SET(CMAKE_CXX_STANDARD 11)
@@ -92,16 +105,9 @@ ENDIF(MPM_DEVICE STREQUAL tests)
MESSAGE("usrp_periphs objects: ${usrp_periphs_objects}")
ADD_LIBRARY(usrp-periphs SHARED ${usrp_periphs_objects})
-TARGET_LINK_LIBRARIES(usrp-periphs udev)
-########################################################################
-# Setup Python API
-########################################################################
+TARGET_LINK_LIBRARIES(usrp-periphs
+ udev
+ ${Boost_LIBRARIES}
+)
-SET(PYTHON_ADDITIONAL_VERSIONS 2.7 3.4 3.5)
-FIND_PACKAGE(PythonInterp)
-unset(PYTHON_LIBRARY)
-unset(PYTHON_EXECUTABLE)
-FIND_PACKAGE(PythonLibs)
ADD_SUBDIRECTORY(python)
-
-########################################################################
diff --git a/mpm/dboards/magnesium_manager.hpp b/mpm/dboards/magnesium_manager.hpp
index ca8a7e123..3c8f038ed 100644
--- a/mpm/dboards/magnesium_manager.hpp
+++ b/mpm/dboards/magnesium_manager.hpp
@@ -48,3 +48,13 @@ namespace mpm { namespace dboards {
}};
+
+#ifdef LIBMPM_PYTHON
+void export_dboards(){
+ LIBMPM_BOOST_PREAMBLE("dboards")
+ bp::class_<mpm::dboards::magnesium_periph_manager>("magnesium_periph_manager", bp::init<std::string, std::string>())
+ .def("get_clock_ctrl", &mpm::dboards::magnesium_periph_manager::get_clock_ctrl)
+ .def("get_radio_ctrl", &mpm::dboards::magnesium_periph_manager::get_radio_ctrl)
+ ;
+}
+#endif
diff --git a/mpm/include/lmk/lmk04828_spi_iface.hpp b/mpm/include/lmk/lmk04828_spi_iface.hpp
index 013271af1..fa11029a8 100644
--- a/mpm/include/lmk/lmk04828_spi_iface.hpp
+++ b/mpm/include/lmk/lmk04828_spi_iface.hpp
@@ -25,3 +25,16 @@ private:
void spi_write(std::vector<uint32_t> writes);
uint8_t spi_read(uint32_t addr);
};
+
+#ifdef LIBMPM_PYTHON
+void export_lmk(){
+ LIBMPM_BOOST_PREAMBLE("lmk04828")
+ bp::class_<lmk04828_iface, boost::shared_ptr<lmk04828_iface>, boost::noncopyable >("lmk04828_iface", bp::no_init)
+ .def("make", &lmk04828_iface::make)
+ .def("verify_chip_id", &lmk04828_iface::verify_chip_id)
+ .def("get_chip_id", &lmk04828_iface::get_chip_id)
+ .def("init", &lmk04828_iface::init)
+ .def("send_sysref_pulse", &lmk04828_iface::send_sysref_pulse)
+ ;
+}
+#endif
diff --git a/mpm/include/mpm/spi/spidev_iface.hpp b/mpm/include/mpm/spi/spidev_iface.hpp
index fb82ffade..ef5303f7b 100644
--- a/mpm/include/mpm/spi/spidev_iface.hpp
+++ b/mpm/include/mpm/spi/spidev_iface.hpp
@@ -57,3 +57,36 @@ namespace mpm { namespace spi {
}}; /* namespace mpm */
+//void export_spi(){
+ //// Register submodule spi
+ //bp::object spi_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs.spi"))));
+ //bp::scope().attr("spi") = spi_module;
+ //bp::scope io_scope = spi_module;
+
+ //bp::class_<spi_lock, boost::noncopyable, boost::shared_ptr<spi_lock> >("spi_lock", bp::no_init)
+ //.def("make", &spi_lock::make)
+ //.def("get_spidev", &spi_lock::get_spidev)
+ //;
+
+ //bp::class_<mpm::spi_iface, boost::noncopyable>("spi_iface", bp::no_init)
+ //.def("write_byte", &mpm::spi_iface::write_byte)
+ //.def("write_bytes", &mpm::spi_iface::write_bytes)
+ //.def("read_byte", &mpm::spi_iface::read_byte)
+ //.def("write_field", &mpm::spi_iface::write_field)
+ //.def("read_field", &mpm::spi_iface::read_field)
+ //.def("get_wire_mode", &mpm::spi_iface::get_wire_mode)
+ //.def("get_endianness", &mpm::spi_iface::get_endianness)
+ //.def("get_chip_select", &mpm::spi_iface::get_chip_select)
+ //;
+
+ //bp::enum_<mpm::spi_iface::spi_endianness_t>("spi_endianness")
+ //.value("lsb_first", mpm::spi_iface::spi_endianness_t::LSB_FIRST)
+ //.value("msb_first", mpm::spi_iface::spi_endianness_t::MSB_FIRST)
+ //;
+
+ //bp::enum_<mpm::spi_iface::spi_wire_mode_t>("spi_wire_mode")
+ //.value("three_wire_mode", mpm::spi_iface::spi_wire_mode_t::THREE_WIRE_MODE)
+ //.value("four_wire_mode", mpm::spi_iface::spi_wire_mode_t::FOUR_WIRE_MODE)
+ //;
+//}
+
diff --git a/mpm/lib/CMakeLists.txt b/mpm/lib/CMakeLists.txt
index 19dbf6dce..647697c84 100644
--- a/mpm/lib/CMakeLists.txt
+++ b/mpm/lib/CMakeLists.txt
@@ -25,4 +25,8 @@ ADD_SUBDIRECTORY(mykonos)
ADD_SUBDIRECTORY(lmk04828)
USRP_PERIPHS_ADD_OBJECT(periphs
- print_foo.cpp)
+ net_helper.cpp
+ udev_helper.cpp
+ xbar_iface.cpp
+ print_foo.cpp
+ )
diff --git a/mpm/lib/lmk04828/CMakeLists.txt b/mpm/lib/lmk04828/CMakeLists.txt
index 4235cb34a..b3621034a 100644
--- a/mpm/lib/lmk04828/CMakeLists.txt
+++ b/mpm/lib/lmk04828/CMakeLists.txt
@@ -2,7 +2,9 @@ MACRO(ETTUS_PYTHON_GEN_SOURCE pyfile outfile)
#ensure that the directory exists for outfile
GET_FILENAME_COMPONENT(outfile_dir ${outfile} PATH)
FILE(MAKE_DIRECTORY ${outfile_dir})
-
+ IF(NOT PYTHON_EXECUTABLE)
+ MESSAGE( FATAL_ERROR "No python executable found to generate ic_regmaps!" )
+ ENDIF(NOT PYTHON_EXECUTABLE)
#make the outfile depend on the python script
ADD_CUSTOM_COMMAND(
OUTPUT ${outfile} DEPENDS ${pyfile} ${ETTUS_PYTHON_GEN_SOURCE_DEPS}
diff --git a/mpm/lib/mykonos/ad937x_ctrl.hpp b/mpm/lib/mykonos/ad937x_ctrl.hpp
index defb57fa2..12c165dab 100644
--- a/mpm/lib/mykonos/ad937x_ctrl.hpp
+++ b/mpm/lib/mykonos/ad937x_ctrl.hpp
@@ -70,3 +70,32 @@ protected:
static std::set<size_t> _get_valid_fir_lengths(const std::string& which);
};
+
+#ifdef LIBMPM_PYTHON
+void export_mykonos(){
+ LIBMPM_BOOST_PREAMBLE("ad937x")
+
+ bp::class_<ad937x_ctrl, boost::noncopyable, std::shared_ptr<ad937x_ctrl> >("ad937x_ctrl", bp::no_init)
+ .def("make", &ad937x_ctrl::make)
+ .def("get_rf_freq_range", &ad937x_ctrl::get_rf_freq_range)
+ .def("get_bw_filter_range", &ad937x_ctrl::get_bw_filter_range)
+ .def("get_clock_rates", &ad937x_ctrl::get_clock_rates)
+ .def("get_gain_range", &ad937x_ctrl::get_gain_range)
+ .def("get_product_id", &ad937x_ctrl::get_product_id)
+ .def("get_device_rev", &ad937x_ctrl::get_device_rev)
+ .def("get_api_version", &ad937x_ctrl::get_api_version)
+ .def("get_arm_version", &ad937x_ctrl::get_arm_version)
+ .def("set_bw_filter", &ad937x_ctrl::set_bw_filter)
+ .def("set_gain", &ad937x_ctrl::set_gain)
+ .def("set_agc_mode", &ad937x_ctrl::set_agc_mode)
+ .def("set_clock_rate", &ad937x_ctrl::set_clock_rate)
+ .def("enable_channel", &ad937x_ctrl::enable_channel)
+ .def("set_freq", &ad937x_ctrl::set_freq)
+ .def("get_freq", &ad937x_ctrl::get_freq)
+ .def("set_fir", &ad937x_ctrl::set_fir)
+ .def("get_fir", &ad937x_ctrl::get_fir)
+ .def("get_temperature", &ad937x_ctrl::get_temperature)
+ ;
+}
+#endif
+
diff --git a/mpm/lib/net_helper.cpp b/mpm/lib/net_helper.cpp
new file mode 100644
index 000000000..0da8de3cf
--- /dev/null
+++ b/mpm/lib/net_helper.cpp
@@ -0,0 +1,118 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 "net_helper.hpp"
+#include <uhd/exception.hpp>
+#include <boost/format.hpp>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <linux/if_link.h>
+#include <linux/if_packet.h>
+#include <iomanip>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <cstring>
+#include <cstdint>
+
+namespace mpm {
+namespace network{
+
+template <typename ArrayType>
+std::string bytearray_to_string(const ArrayType array[], size_t elements) {
+ std::stringstream result;
+ for (size_t i = 0; i < elements; i++) {
+ result << std::uppercase << std::setfill('0')
+ << std::setw(sizeof(array[i]) *
+ 2) // always produce 2 hex values for each byte
+ << std::hex << +array[i]; // Implicit integer promotion
+ }
+ return result.str();
+}
+
+void print_net_ifaces(net_ifaces my_ifaces) {
+ /* take in a net_ifaces and pretty print information
+ about all detected network interfaces */
+ for (const auto& iface : my_ifaces) {
+ std::cout << "interface: " << iface.first << std::endl;
+ std::cout << "\tMAC: " << iface.second.mac_addr << std::endl;
+ for (const auto& addr : iface.second.ip_addr) {
+ std::cout << "\tip address: " << addr << std::endl;
+ }
+ }
+}
+
+net_ifaces get_net_map() {
+ /* Get a map containing a string and a net_iface struct
+ to describe all adresses assigned to a interface */
+ struct ifaddrs *ifaddr, *ifa;
+ int family, s;
+ char host[NI_MAXHOST];
+ net_ifaces net_map;
+
+ if (getifaddrs(&ifaddr) == -1) {
+ throw uhd::system_error(str(boost::format("Error: %s") % strerror(errno)));
+ }
+
+ /* Walk through linked list, maintaining head pointer so we
+ can free list later */
+
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ /* Put the interaface name into the map, if it already exists
+ we get an iterator to the existing element */
+ auto result = net_map.emplace(
+ std::make_pair(std::string(ifa->ifa_name), net_iface()));
+ auto current_iface = result.first;
+
+ family = ifa->ifa_addr->sa_family;
+ if (family == AF_INET || family == AF_INET6) {
+ s = getnameinfo(ifa->ifa_addr,
+ (family == AF_INET) ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+ if (s != 0) {
+ printf("getnameinfo() failed: %s\n", gai_strerror(s));
+ return net_map;
+ }
+ current_iface->second.ip_addr.push_back(std::string(host));
+ } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
+ struct sockaddr_ll* s = (struct sockaddr_ll*)ifa->ifa_addr;
+ uint8_t mac_addr[6];
+ memcpy(&mac_addr, s->sll_addr, 6);
+ current_iface->second.mac_addr = bytearray_to_string(mac_addr, 6);
+ }
+ }
+ freeifaddrs(ifaddr);
+ return net_map;
+}
+
+std::vector<std::string> get_if_addrs(const std::string& mac_addr) {
+ /* Convenience wrapper to return all adresses associated with one
+ mac address */
+ net_ifaces my_map = get_net_map();
+ for (const auto& iface : my_map) { // find
+ if (iface.second.mac_addr == mac_addr) {
+ return iface.second.ip_addr;
+ }
+ }
+ return std::vector<std::string>();
+}
+}
+}
diff --git a/mpm/lib/net_helper.hpp b/mpm/lib/net_helper.hpp
new file mode 100644
index 000000000..b07e43ccc
--- /dev/null
+++ b/mpm/lib/net_helper.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 <map>
+#include <vector>
+#include <string>
+
+namespace mpm {
+namespace network {
+
+/*!
+ * A struct describing a single network interface
+ */
+using net_iface = struct net_iface {
+ /*! MAC address of the interface in the form AABBCCDDEEFF */
+ std::string mac_addr;
+ /*! vector of associated IP addresses, contains both IPv4 and IPv6 */
+ std::vector<std::string> ip_addr;
+};
+
+/*!
+ * net_ifaces contains a <interfaces name, net_iface> pair
+ * describing mac address and associated ip addresses for
+ * each interface
+ */
+using net_ifaces = std::map<std::string, net_iface>;
+
+/*!
+ * Convenience function to get all ip addresses of one MAC address
+ * \param MAC address in the form AABBCCDDEEFF
+ * \return vector of strings containing all IP addresses with this MAC address
+ */
+std::vector<std::string> get_if_addrs(const std::string& mac_addr);
+
+/*!
+ * Get information about all interfaces on this system
+ * \return a map with interface names as keys and the interfaces information as value
+ */
+net_ifaces get_net_map();
+
+/*!
+ * Pretty print net_ifaces in the style of `ip addr`
+ * \param interface map net_ifaces to print
+ */
+void print_net_ifaces(net_ifaces my_ifaces);
+}
+}
+
+#ifdef LIBMPM_PYTHON
+void export_net_iface(){
+ LIBMPM_BOOST_PREAMBLE("network")
+ bp::def("get_if_addrs", &mpm::network::get_if_addrs);
+}
+#endif
+
diff --git a/mpm/lib/udev_helper.cpp b/mpm/lib/udev_helper.cpp
new file mode 100644
index 000000000..ba12f6667
--- /dev/null
+++ b/mpm/lib/udev_helper.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 "udev_helper.hpp"
+#include <uhd/exception.hpp>
+#include <boost/format.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/crc.hpp>
+#include <utility>
+#include <iostream>
+#include <string>
+#include <cstring>
+#include <fstream>
+
+using namespace mpm;
+
+udev_helper::udev_helper(){
+ _udev = udev_new();
+ if (!_udev) {
+ throw uhd::os_error("Failed to create udev!");
+ }
+ _enumerate = udev_enumerate_new(_udev);
+
+}
+
+udev_helper::~udev_helper(){
+ udev_enumerate_unref(_enumerate);
+ udev_unref(_udev);
+}
+std::string udev_helper::get_eeprom(const std::string &address){
+ udev_list_entry *devices, *dev_list_entry;
+ udev_device *dev, *parent;
+
+ parent = udev_device_new_from_subsystem_sysname(_udev, "platform", address.c_str());
+ if (parent == NULL){
+ return std::string();
+ }
+ udev_enumerate_add_match_parent(_enumerate, parent);
+ udev_enumerate_add_match_subsystem(_enumerate, "nvmem");
+ udev_enumerate_scan_devices(_enumerate);
+
+ devices = udev_enumerate_get_list_entry(_enumerate);
+ if (devices == NULL){
+ return std::string();
+ }
+ udev_list_entry_foreach(dev_list_entry, devices) {
+ const char *path = NULL, *sys_path = NULL;
+ path = udev_list_entry_get_name(dev_list_entry);
+ dev = udev_device_new_from_syspath(_udev, path);
+ sys_path = udev_device_get_syspath(dev);
+ udev_device_unref(dev);
+ return "/sys" + std::string(sys_path) + "/nvmem";
+ }
+ return std::string();
+}
+
+std::vector<std::string> udev_helper::get_spidev_nodes(const std::string &spi_master){
+ udev_list_entry *devices, *dev_list_entry;
+ udev_device *dev, *parent;
+
+ parent = udev_device_new_from_subsystem_sysname(_udev, "platform", spi_master.c_str());
+ udev_enumerate_add_match_parent(_enumerate, parent);
+ udev_enumerate_add_match_subsystem(_enumerate, "spidev");
+ udev_enumerate_scan_devices(_enumerate);
+
+ devices = udev_enumerate_get_list_entry(_enumerate);
+ std::vector<std::string> found_dev_nodes;
+ if (devices != NULL){
+ udev_list_entry_foreach(dev_list_entry, devices){
+ const char *path, *dev_node;
+ path = udev_list_entry_get_name(dev_list_entry);
+ dev = udev_device_new_from_syspath(_udev, path);
+ dev_node = udev_device_get_devnode(dev);
+ found_dev_nodes.push_back(std::string(dev_node));
+ udev_device_unref(dev);
+ }
+ }
+ return found_dev_nodes;
+}
diff --git a/mpm/lib/udev_helper.hpp b/mpm/lib/udev_helper.hpp
new file mode 100644
index 000000000..055a93cee
--- /dev/null
+++ b/mpm/lib/udev_helper.hpp
@@ -0,0 +1,62 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 <libudev.h>
+#include <string>
+#include <vector>
+
+namespace mpm {
+ /*!
+ * The udev_helper class:
+ *
+ * talks to libudev and holds a udev context. Device enumeration is done
+ * once during initialization.
+ * On destruction the udev context is unreferenced again.
+ */
+ class udev_helper{
+ public:
+ udev_helper();
+ ~udev_helper();
+ /*!
+ * Return the nvmem device associated with the parent address
+ * \param address of the parent platform driver
+ * \return a string containing the name of file of the device in /sys
+ */
+ std::string get_eeprom(const std::string &address);
+ /*!
+ * Find spidevices associated with the spi_master
+ * \param address of the parent platform driver
+ * \return a vector of string containing the device paths is /dev
+ */
+ std::vector<std::string> get_spidev_nodes(const std::string &spi_master);
+
+ private:
+ udev *_udev;
+ udev_enumerate *_enumerate;
+ };
+}
+
+#ifdef LIBMPM_PYTHON
+void export_udev_helper(){
+ LIBMPM_BOOST_PREAMBLE("udev")
+ bp::class_<mpm::udev_helper>("udev_helper", bp::init<>())
+ .def("get_eeprom", &mpm::udev_helper::get_eeprom)
+ .def("get_spidev_nodes", &mpm::udev_helper::get_spidev_nodes)
+ ;
+}
+#endif
+
diff --git a/mpm/lib/xbar_iface.cpp b/mpm/lib/xbar_iface.cpp
new file mode 100644
index 000000000..21b60d131
--- /dev/null
+++ b/mpm/lib/xbar_iface.cpp
@@ -0,0 +1,56 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 "xbar_iface.hpp"
+#include <uhd/exception.hpp>
+#include <boost/format.hpp>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+using namespace mpm;
+
+std::mutex xbar_iface::_lock; // Initialize lock for all objects
+
+xbar_iface::xbar_iface(const std::string &device){
+ _fd = open(device.c_str(), O_RDWR);
+}
+
+xbar_iface::~xbar_iface(){
+ close(_fd);
+}
+
+void xbar_iface::set_route(uint8_t dst_addr, uint8_t dst_port) {
+ std::lock_guard<std::mutex> lock(_lock);
+ rfnoc_crossbar_cmd cmd = {.dest_addr = dst_addr, .dest_port = dst_port};
+ int err = ioctl(_fd, RFNCBWROUTIOC, &cmd);
+ if (err < 0) {
+ throw uhd::os_error(str(boost::format("setting crossbar route failed! Error: %d") % err));
+ }
+}
+
+void xbar_iface::del_route(uint8_t dst_addr, uint8_t dst_port){
+ std::lock_guard<std::mutex> lock(_lock);
+ rfnoc_crossbar_cmd cmd = {.dest_addr = dst_addr, .dest_port = dst_port};
+ int err = ioctl(_fd, RFNCDELROUTIOC, &cmd);
+ if (err < 0){
+ throw uhd::os_error(str(boost::format("deleting crossbar route failed! Error: %d") % err));
+ }
+}
+
+xbar_iface::sptr xbar_iface::make(const std::string &device){
+ return std::make_shared<xbar_iface>(device);
+}
diff --git a/mpm/lib/xbar_iface.hpp b/mpm/lib/xbar_iface.hpp
new file mode 100644
index 000000000..9b17ed97b
--- /dev/null
+++ b/mpm/lib/xbar_iface.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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/>.
+//
+#pragma once
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <mutex>
+#include <cstdint>
+
+namespace mpm{
+
+/*!
+ * Crossbar route command
+ */
+using rfnoc_crossbar_cmd = struct rfnoc_crossbar_cmd {
+ /*! destination address */
+ uint8_t dest_addr;
+ /*! destination port */
+ uint8_t dest_port;
+};
+
+#define RFNCBWROUTIOC _IOW('R', 1, struct rfnoc_crossbar_cmd)
+#define RFNCDELROUTIOC _IOW('D', 1, struct rfnoc_crossbar_cmd)
+
+/*!
+ * Crossbar interface class holding a crossbar context
+ */
+class xbar_iface: boost::noncopyable{
+public:
+ // use static mutex! lock_guard
+ using sptr = std::shared_ptr<xbar_iface>;
+ static sptr make(const std::string &device);
+ void set_route(uint8_t dst_addr, uint8_t dst_port);
+ void del_route(uint8_t dst_addr, uint8_t dst_port);
+ ~xbar_iface();
+ xbar_iface(const std::string &device);
+
+private:
+ static std::mutex _lock;
+ int _fd;
+};
+}
+
+
+#ifdef LIBMPM_PYTHON
+void export_xbar(){
+ LIBMPM_BOOST_PREAMBLE("xbar")
+ bp::class_<mpm::xbar_iface, boost::noncopyable, std::shared_ptr<mpm::xbar_iface> >("xbar", bp::no_init)
+ .def("make", &mpm::xbar_iface::make)
+ .staticmethod("make")
+ .def("set_route", &mpm::xbar_iface::set_route)
+ .def("del_route", &mpm::xbar_iface::del_route)
+ ;
+}
+#endif
+
diff --git a/mpm/python/CMakeLists.txt b/mpm/python/CMakeLists.txt
index 7d3b251d7..7a88abfc7 100644
--- a/mpm/python/CMakeLists.txt
+++ b/mpm/python/CMakeLists.txt
@@ -24,13 +24,14 @@ SET(UHD_HOST_ROOT ${CMAKE_SOURCE_DIR}/../host)
LIST(APPEND
pyusrp_periphs_sources
pyusrp_periphs.cpp
- lib_periphs.cpp
- n310_periphs.cpp
- # tests_periphs.cpp
- )
+)
ADD_LIBRARY(pyusrp_periphs SHARED ${pyusrp_periphs_sources})
-TARGET_INCLUDE_DIRECTORIES(pyusrp_periphs PUBLIC ${PYTHON_INCLUDE_DIRS} ${UHD_HOST_ROOT}/lib/usrp/common)
+TARGET_INCLUDE_DIRECTORIES(pyusrp_periphs PUBLIC
+ ${PYTHON_INCLUDE_DIRS}
+ ${CMAKE_SOURCE_DIR}/lib/
+ ${UHD_HOST_ROOT}/lib/usrp/common
+)
TARGET_LINK_LIBRARIES(pyusrp_periphs ${Boost_PYTHON_LIBRARY} ${Boost_LIBRARIES} usrp-periphs)
ADD_CUSTOM_COMMAND(TARGET pyusrp_periphs POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libpyusrp_periphs.so ${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm/libpyusrp_periphs.so)
@@ -43,10 +44,10 @@ SET(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp")
CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY})
ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT}
- COMMAND ${CMAKE_COMMAND} -E copy ${USRP_MPM_FILES} ${CMAKE_CURRENT_BINARY_DIR}/usrp_mpm
- COMMAND ${PYTHON} ${SETUP_PY} -q build
- COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
- DEPENDS ${USRP_MPM_FILES})
+ COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" -DBINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}" -P ${CMAKE_CURRENT_SOURCE_DIR}/copy_python_module.cmake
+ COMMAND ${PYTHON} ${SETUP_PY} -q build
+ COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
+ DEPENDS ${USRP_MPM_FILES})
ADD_CUSTOM_TARGET(usrp_mpm ALL DEPENDS ${OUTPUT} pyusrp_periphs)
EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c
diff --git a/mpm/python/converters.hpp b/mpm/python/converters.hpp
new file mode 100644
index 000000000..dc977b698
--- /dev/null
+++ b/mpm/python/converters.hpp
@@ -0,0 +1,105 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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/>.
+//
+
+#pragma once
+
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <vector>
+#include <string>
+
+namespace bp = boost::python;
+
+template<typename MapType>
+struct map_to_python_dict
+{
+ static PyObject* convert(MapType const& input_map)
+ {
+ bp::dict py_dict;
+ for (const auto& element: input_map){
+ py_dict[element.first] = element.second;
+ }
+ return bp::incref(py_dict.ptr());
+ }
+
+};
+
+template<typename Container>
+struct iterable_to_python_list
+{
+ static PyObject* convert(Container const& input)
+ {
+ bp::list py_list;
+ for (const auto& element: input){
+ py_list.append(element);
+ }
+ return bp::incref(py_list.ptr());
+ }
+};
+
+// Converter for std::vector / std::list arguments from python iterables
+struct iterable_converter
+{
+ template <typename Container>
+ iterable_converter&
+ from_python()
+ {
+ bp::converter::registry::push_back(
+ &iterable_converter::convertible,
+ &iterable_converter::construct<Container>,
+ bp::type_id<Container>());
+ return *this;
+ }
+
+ static void* convertible(PyObject* object)
+ {
+ return PyObject_GetIter(object) ? object : NULL;
+ }
+
+ template <typename Container>
+ static void construct(
+ PyObject* object,
+ bp::converter::rvalue_from_python_stage1_data* data)
+ {
+ // Object is a borrowed reference, so create a handle indicting it is
+ // borrowed for proper reference counting.
+ bp::handle<> handle(bp::borrowed(object));
+
+ // Obtain a handle to the memory block that the converter has allocated
+ // for the C++ type.
+ typedef bp::converter::rvalue_from_python_storage<Container>
+ storage_type;
+ void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
+
+ typedef bp::stl_input_iterator<typename Container::value_type>
+ iterator;
+
+ // Allocate the C++ type into the converter's memory block, and assign
+ // its handle to the converter's convertible variable. The C++
+ // container is populated by passing the begin and end iterators of
+ // the python object to the container's constructor.
+ new (storage) Container(
+ iterator(bp::object(handle)), // begin
+ iterator()); // end
+ data->convertible = storage;
+ }
+};
+
+void export_converter(){
+ // LIBMPM_BOOST_PREAMBLE("helper")
+ bp::to_python_converter<std::vector< std::string >, iterable_to_python_list<std::vector< std::string > >, false>();
+}
diff --git a/mpm/python/copy_python_module.cmake b/mpm/python/copy_python_module.cmake
new file mode 100644
index 000000000..1b36d4fab
--- /dev/null
+++ b/mpm/python/copy_python_module.cmake
@@ -0,0 +1,4 @@
+SET(BINARY_DIR "" CACHE STRING "")
+SET(SOURCE_DIR "" CACHE STRING "")
+FILE(COPY ${SOURCE_DIR}/usrp_mpm/ DESTINATION ${BINARY_DIR}/usrp_mpm
+ FILES_MATCHING PATTERN *.py)
diff --git a/mpm/python/lib_helper.cpp b/mpm/python/lib_helper.cpp
new file mode 100644
index 000000000..5948628f8
--- /dev/null
+++ b/mpm/python/lib_helper.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 "lib_helper.hpp"
+#include "converters.hpp"
+#include "../lib/udev_helper.hpp"
+#include "../lib/net_helper.hpp"
+#include <boost/python.hpp>
+
+namespace bp = boost::python;
+
+void export_helper(){
+ //Register submodule types
+ bp::object helper_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs.helper"))));
+ bp::scope().attr("helper") = helper_module;
+ bp::scope io_scope = helper_module;
+
+ bp::class_<mpm::udev_helper>("udev_helper", bp::init<>())
+ .def("get_eeprom", &mpm::udev_helper::get_eeprom)
+ ;
+ bp::def("get_if_addrs", &mpm::network::get_if_addrs);
+ bp::to_python_converter<std::vector< std::string >, iterable_to_python_list<std::vector< std::string > >, false>();
+}
+
diff --git a/mpm/python/lib_periphs.cpp b/mpm/python/lib_periphs.cpp
deleted file mode 100644
index 030752ede..000000000
--- a/mpm/python/lib_periphs.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "lib_periphs.hpp"
-#include "lmk04828.hpp"
-#include <mpm/spi_iface.hpp>
-#include <boost/python.hpp>
-
-namespace bp = boost::python;
-
-void export_lmk(){
- //Register submodule types
- bp::object lmk_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs.lmk"))));
- bp::scope().attr("lmk") = lmk_module;
- bp::scope io_scope = lmk_module;
-
- bp::class_<lmk04828_iface, boost::shared_ptr<lmk04828_iface>, boost::noncopyable >("lmk04828_iface", bp::no_init)
- .def("make", &lmk04828_iface::make)
- .def("verify_chip_id", &lmk04828_iface::verify_chip_id)
- .def("init", &lmk04828_iface::init)
- .def("send_sysref_pulse", &lmk04828_iface::send_sysref_pulse)
- ;
-}
-
-void export_spi(){
- //Register submodule types
- bp::object spi_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs.spi"))));
- bp::scope().attr("spi") = spi_module;
- bp::scope io_scope = spi_module;
-
- bp::class_<mpm::spi_iface, boost::noncopyable>("spi_iface", bp::no_init)
- .def("write_byte", &mpm::spi_iface::write_byte)
- .def("write_bytes", &mpm::spi_iface::write_bytes)
- .def("read_byte", &mpm::spi_iface::read_byte)
- .def("write_field", &mpm::spi_iface::write_field)
- .def("read_field", &mpm::spi_iface::read_field)
- .def("get_wire_mode", &mpm::spi_iface::get_wire_mode)
- .def("get_endianness", &mpm::spi_iface::get_endianness)
- .def("get_chip_select", &mpm::spi_iface::get_chip_select)
- ;
-
- bp::enum_<mpm::spi_iface::spi_endianness_t>("spi_endianness")
- .value("lsb_first", mpm::spi_iface::spi_endianness_t::LSB_FIRST)
- .value("msb_first", mpm::spi_iface::spi_endianness_t::MSB_FIRST)
- ;
-
- bp::enum_<mpm::spi_iface::spi_wire_mode_t>("spi_wire_mode")
- .value("three_wire_mode", mpm::spi_iface::spi_wire_mode_t::THREE_WIRE_MODE)
- .value("four_wire_mode", mpm::spi_iface::spi_wire_mode_t::FOUR_WIRE_MODE)
- ;
-}
-
diff --git a/mpm/python/lib_periphs.hpp b/mpm/python/lib_periphs.hpp
deleted file mode 100644
index 2ea023c5c..000000000
--- a/mpm/python/lib_periphs.hpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-void export_lmk();
-void export_spi();
diff --git a/mpm/python/n310_periphs.cpp b/mpm/python/n310_periphs.cpp
deleted file mode 100644
index 42fea61b1..000000000
--- a/mpm/python/n310_periphs.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "n310_periphs.hpp"
-#include "../n310/periph_manager.hpp"
-#include <boost/python.hpp>
-#include <memory>
-
-namespace bp = boost::python;
-
-void export_n3xx(){
- //Register submodule types
- bp::object n3xx_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs.n3xx"))));
- bp::scope().attr("n3xx") = n3xx_module;
- bp::scope io_scope = n3xx_module;
-
- bp::class_<mpm::n3xx::n3xx_dboard_periph_manager, boost::noncopyable>("dboard_periph_manager", bp::no_init)
- .def("get_clock_gen()", &mpm::n3xx::n3xx_dboard_periph_manager::get_clock_gen)
- ;
- bp::class_<mpm::n3xx::periph_manager, boost::noncopyable, std::shared_ptr<mpm::n3xx::periph_manager> >("periph_manager", bp::init<std::string>())
- .def("get_dboard_A", &mpm::n3xx::periph_manager::get_dboard_A)
- ;
-}
-
diff --git a/mpm/python/n310_periphs.hpp b/mpm/python/n310_periphs.hpp
deleted file mode 100644
index b4e418947..000000000
--- a/mpm/python/n310_periphs.hpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-void export_n3xx();
diff --git a/mpm/python/pyusrp_periphs.cpp b/mpm/python/pyusrp_periphs.cpp
index 5a49398c4..348e19c5c 100644
--- a/mpm/python/pyusrp_periphs.cpp
+++ b/mpm/python/pyusrp_periphs.cpp
@@ -1,8 +1,39 @@
-#include "n310_periphs.hpp"
-// #include "tests_periphs.hpp"
-#include "lib_periphs.hpp"
-#include <mpm/print_foo.hpp>
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 hackery to only include boost python and define the macro here
#include <boost/python.hpp>
+#define LIBMPM_PYTHON
+#define LIBMPM_BOOST_PREAMBLE(module) \
+ /* Register submodule types */ \
+ namespace bp = boost::python; \
+ bp::object py_module(bp::handle<>(bp::borrowed(PyImport_AddModule("libpyusrp_periphs." module)))); \
+ bp::scope().attr(module) = py_module; \
+ bp::scope io_scope = py_module;
+
+//#include "types.hpp"
+#include "converters.hpp"
+#include "net_helper.hpp"
+#include "xbar_iface.hpp"
+#include "udev_helper.hpp"
+#include "mykonos/ad937x_ctrl.hpp"
+#include "lmk/lmk04828_spi_iface.hpp"
+//#include "lib_periphs.hpp"
+//#include "dboards.hpp"
#include <boost/noncopyable.hpp>
namespace bp = boost::python;
@@ -11,9 +42,13 @@ BOOST_PYTHON_MODULE(libpyusrp_periphs)
{
bp::object package = bp::scope();
package.attr("__path__") = "libpyusrp_periphs";
- bp::def("print_foo", &mpm::print_foo);
- export_spi();
- // export_tests();
- export_lmk();
- export_n3xx();
+ export_converter();
+ export_net_iface();
+ //export_types();
+ export_udev_helper();
+ //export_spi();
+ //export_lmk();
+ export_mykonos();
+ export_xbar();
+ //export_dboards();
}
diff --git a/mpm/python/setup.py.in b/mpm/python/setup.py.in
index ad41eb480..2a63d14aa 100755
--- a/mpm/python/setup.py.in
+++ b/mpm/python/setup.py.in
@@ -38,7 +38,7 @@ setup(name='usrp_mpm',
package_dir={ '': '${CMAKE_CURRENT_BINARY_DIR}' },
package_data={"usrp_mpm": ["*.so"]},
zip_safe=False,
- packages=['usrp_mpm'],
+ packages=['usrp_mpm', 'usrp_mpm.periph_manager', 'usrp_mpm.dboard_manager'],
install_requires=[
'numpy'
])
diff --git a/mpm/python/tests_periphs.cpp b/mpm/python/tests_periphs.cpp
index 15c1b08b6..a35d00265 100644
--- a/mpm/python/tests_periphs.cpp
+++ b/mpm/python/tests_periphs.cpp
@@ -1,3 +1,20 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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 "tests_periphs.hpp"
#include <mpm/tests/tests_spi_iface.hpp>
#include <mpm/spi_iface.hpp>
@@ -11,7 +28,7 @@ void export_tests(){
bp::scope().attr("tests") = tests_module;
bp::scope io_scope = tests_module;
- bp::class_<mpm::tests_spi_iface, bp::bases<mpm::spi_iface>, std::shared_ptr<mpm::tests_spi_iface> >("test_spi_iface", bp::init<>())
+ bp::class_<mpm::tests_spi_iface, bp::bases<mpm::spi_iface>, boost::shared_ptr<mpm::tests_spi_iface> >("test_spi_iface", bp::init<>())
.def("make", &mpm::tests_spi_iface::make)
.staticmethod("make")
;
diff --git a/mpm/python/tests_periphs.hpp b/mpm/python/tests_periphs.hpp
index 4b978269d..e80dccdb2 100644
--- a/mpm/python/tests_periphs.hpp
+++ b/mpm/python/tests_periphs.hpp
@@ -1,3 +1,20 @@
+//
+// Copyright 2017 Ettus Research (National Instruments)
+//
+// 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/>.
+//
+
#pragma once
void export_tests();
diff --git a/mpm/python/usrp_mpm/CMakeLists.txt b/mpm/python/usrp_mpm/CMakeLists.txt
index ad3ce41fd..f8f94bb5d 100644
--- a/mpm/python/usrp_mpm/CMakeLists.txt
+++ b/mpm/python/usrp_mpm/CMakeLists.txt
@@ -26,5 +26,7 @@ SET(USRP_MPM_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rpc_process.py
${CMAKE_CURRENT_SOURCE_DIR}/rpc_server.py
${CMAKE_CURRENT_SOURCE_DIR}/periphs.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/periph_manager
+ ${CMAKE_CURRENT_SOURCE_DIR}/dboard_manager
PARENT_SCOPE
)
diff --git a/mpm/python/usrp_mpm/__init__.py b/mpm/python/usrp_mpm/__init__.py
index dafb6940c..c349d3d77 100644
--- a/mpm/python/usrp_mpm/__init__.py
+++ b/mpm/python/usrp_mpm/__init__.py
@@ -21,3 +21,5 @@ MPM Module
from discovery import spawn_discovery_process
from rpc_process import spawn_rpc_process
import types
+import periph_manager
+import dboard_manager
diff --git a/mpm/python/usrp_mpm/dboard_manager/__init__.py b/mpm/python/usrp_mpm/dboard_manager/__init__.py
new file mode 100644
index 000000000..774f348d4
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/__init__.py
@@ -0,0 +1,28 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+dboards module __init__.py
+"""
+from .. import libpyusrp_periphs as lib
+from magnesium import magnesium
+from eiscat import eiscat
+from unknown import unknown
+
+hw_pids = {
+ eiscat.hw_pid: eiscat,
+ magnesium.hw_pid: magnesium,
+}
diff --git a/mpm/python/usrp_mpm/dboard_manager/base.py b/mpm/python/usrp_mpm/dboard_manager/base.py
new file mode 100644
index 000000000..bf0a115cc
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/base.py
@@ -0,0 +1,37 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+dboard base implementation module
+"""
+from . import lib
+import logging
+import struct
+
+log = logging.Logger("usrp_mpm.dboards")
+
+
+class dboard_manager(object):
+ """
+ Holds shared pointer to wrapped C++ implementation.
+ Sanitizes arguments before calling C++ functions.
+ Ties various constants to specific daughterboard class
+ """
+ def __init__(self, eeprom={}):
+ self._eeprom = eeprom
+
+ def get_serial(self):
+ return self._eeprom.get("serial", "")
diff --git a/mpm/python/usrp_mpm/dboard_manager/eiscat.py b/mpm/python/usrp_mpm/dboard_manager/eiscat.py
new file mode 100644
index 000000000..f536d307b
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/eiscat.py
@@ -0,0 +1,31 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+EISCAT rx board implementation module
+"""
+from base import dboard_manager
+from base import lib
+from base import log
+
+
+class eiscat(dboard_manager):
+ hw_pid = 3
+ special_eeprom_addrs = {"special0": "something"}
+
+ def __init__(self, spidevs=[], *args, **kwargs):
+ # Do own init
+ super(eiscat, self).__init__(*args, **kwargs)
diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py
new file mode 100644
index 000000000..2201064ad
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py
@@ -0,0 +1,50 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+magnesium dboard implementation module
+"""
+from base import dboard_manager
+from base import lib
+from base import log
+
+class magnesium(dboard_manager):
+ hw_pid = 2
+ special_eeprom_addrs = {"special0": "something"}
+ spi_chipselect = {"0": "lmk", "1": "mykonos", "2": "random"}
+ spidevs = {}
+
+ def __init__(self, spi_devices, eeprom_data, *args, **kwargs):
+ # eeprom_data is a tuple (head_dict, raw_data)
+ if len(spi_devices) != len(self.spi_chipselect):
+ log.error("Expected {0} spi devices, found {1} spi devices".format(len(spi_devices), len(self.spi_chipselect)))
+ exit(1)
+ for spi in spi_devices:
+ device = self.spi_chipselect.get(spi[-1], None)
+ if self.chipselect is None:
+ log.error("Unexpected chipselect {0}".format(spi[-1]))
+ exit(1)
+ setattr(self, device, spi)
+ super(magnesium, self).__init__(*args, **kwargs)
+
+ def init_device(self):
+ self._device = lib.db.magnesium(self.lmk, self.mykonos, self.random)
+
+ def read_eeprom_v1(self, data):
+ # magnesium eeprom contains
+ # nothing
+ return struct.unpack_from("x", data)
+
diff --git a/mpm/python/usrp_mpm/dboard_manager/unknown.py b/mpm/python/usrp_mpm/dboard_manager/unknown.py
new file mode 100644
index 000000000..f33bacc46
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/unknown.py
@@ -0,0 +1,32 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+EISCAT rx board implementation module
+"""
+from base import dboard_manager
+from base import lib
+from base import log
+
+
+class unknown(dboard_manager):
+ hw_pid = 0
+ special_eeprom_addrs = {}
+
+ def __init__(self, spi_devices, eeprom_data):
+ self._eeprom = eeprom_data[0] # save eeprom header
+ # Do own init
+ super(unknown, self).__init__()
diff --git a/mpm/python/usrp_mpm/helper.py b/mpm/python/usrp_mpm/helper.py
new file mode 100644
index 000000000..29864124a
--- /dev/null
+++ b/mpm/python/usrp_mpm/helper.py
@@ -0,0 +1,3 @@
+
+
+class eeprom_helper:
diff --git a/mpm/python/usrp_mpm/periph_manager/__init__.py b/mpm/python/usrp_mpm/periph_manager/__init__.py
new file mode 100644
index 000000000..96eecf62e
--- /dev/null
+++ b/mpm/python/usrp_mpm/periph_manager/__init__.py
@@ -0,0 +1,29 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+periph_manager __init__.py
+"""
+
+# This is where the import magic happens
+from .. import libpyusrp_periphs as lib
+from .. import dboard_manager
+from .. import types
+
+try:
+ from n310 import n310 as periph_manager
+except ImportError:
+ raise("Could not import n310")
diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py
new file mode 100644
index 000000000..f19265a05
--- /dev/null
+++ b/mpm/python/usrp_mpm/periph_manager/base.py
@@ -0,0 +1,75 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+Mboard implementation base class
+"""
+
+import re
+import os
+from . import lib
+from . import types
+from . import dboard_manager
+
+
+class periph_manager(object):
+ # stores discovered device information in dicts
+ dboards = {}
+ mboard_if_addrs = {}
+ mboard_overlays = {}
+ # this information has to be provided by
+ # the specific periph_manager implementation
+ mboard_eeprom_addr = ""
+ dboard_eeprom_addrs = {}
+ dboard_spimaster_addrs = {}
+
+ def __init__(self):
+ # I know my EEPROM address, lets use it
+ helper = lib.udev_helper.udev_helper()
+ (self._eeprom_head, self._eeprom_rawdata) = types.eeprom().read_eeprom(helper.get_eeprom(self.mboard_eeprom_addr))
+ self._dboard_eeproms = {}
+ for dboard_slot, eeprom_addr in self.dboard_eeprom_addrs.iteritems():
+ spi_devices = []
+ # I know EEPROM adresses for my dboard slots
+ eeprom_data = types.eeprom().read(helper.get_eeprom(eeprom_addr))
+ # I know spidev masters on the dboard slots
+ hw_pid = eeprom_data.get("hw_pid", 0)
+ if hw_pid in dboards.hw_pids:
+ spi_devices = helper.get_spidev_nodes(self.dboard_spimaster_addrs.get(dboard_slot))
+ dboard = dboards.hw_pids.get(hw_pid, dboards.unknown)
+ self.dboards.update({dboard_slot: dboard(spi_devices, eeprom_data)})
+
+ def get_overlays(self):
+ self.mboard_overlays = []
+ for f in os.listdir("/lib/firmware/"):
+ if f.endswith(".dtbo"):
+ self.mboard_overlays.append(f.strip(".dtbo"))
+
+ def check_overlay(self):
+ for f in os.listdir("/sys/kernel/device-tree/overlays/"):
+ pass #do stuff
+
+ def get_serial(self):
+ return self._serial
+
+ def load_fpga_image(self, target=None):
+ pass
+
+ def init_device(self, *args, **kwargs):
+ # Load FPGA
+ # Init dboards
+ pass
+
diff --git a/mpm/python/usrp_mpm/periph_manager/n310.py b/mpm/python/usrp_mpm/periph_manager/n310.py
new file mode 100644
index 000000000..e270387f6
--- /dev/null
+++ b/mpm/python/usrp_mpm/periph_manager/n310.py
@@ -0,0 +1,46 @@
+#
+# Copyright 2017 Ettus Research (National Instruments)
+#
+# 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/>.
+#
+"""
+N310 implementation module
+"""
+from base import periph_manager
+import struct
+
+
+class n310(periph_manager):
+ hw_pids = "1"
+ mboard_eeprom_addr = "e0007000.spi:ec@0:i2c-tunnel"
+ dboard_eeprom_addrs = {"A": "something", "B": "else"}
+ dboard_spimaster_addrs = {"A": "something", "B": "else"}
+
+ def __init__(self, eeprom_device, *args, **kwargs):
+ # First initialize parent class - will populate self._eeprom_head and self._eeprom_rawdata
+ super(n310, self).__init__(*args, **kwargs)
+ data = self.read_eeprom_v1(self._eeprom_rawdata)
+ print(data)
+ # if header.get("dataversion", 0) == 1:
+
+ def read_eeprom_v1(self, data):
+ # data_version contains
+ # 6 bytes mac_addr0
+ # 2 bytes pad
+ # 6 bytes mac_addr1
+ # 2 bytes pad
+ # 6 bytes mac_addr2
+ # 2 bytes pad
+ # 8 bytes serial
+ return struct.unpack_from("6s 2x 6s 2x 6s 2x 8s", data)
diff --git a/mpm/python/usrp_mpm/periphs.py b/mpm/python/usrp_mpm/periphs.py
index 3a78f224b..8c00d8f50 100644
--- a/mpm/python/usrp_mpm/periphs.py
+++ b/mpm/python/usrp_mpm/periphs.py
@@ -19,52 +19,19 @@
"""
import libpyusrp_periphs as lib
-import re
import logging
-log = logging.Logger("usrp_mpm.periphs")
+import periph_manager
+import dboard_manager
+
+log = logging.Logger("usrp_mpm.periphs")
def init_periph_manager(mb_type=None, db_types={}, fpga=None):
- # Detect motherboard type if not already specified
- if mb_type is None:
- mb_files = lib.helper.find_mb_file()
- with open(mb_files, "r") as f:
- info = "".join(f.readlines())
- device_type = re.match("^.*USRP;([-\w])+;.*", info)
- if device_type is None:
- log.fatal("Could not determine device type from {}".format(info))
- exit(1)
- mb_type = device_type.group(1)
- # Check if we have an implementation for this motherboard type
- try:
- device_class = getattr(lib, mb_type)
- except AttributeError:
- log.fatal("Motherboard class implementation for {} device not found!".format(mb_type))
- exit(1)
+ pass
+ # Moved to periph_manager/base.py __init__
- # Detect daughterboard type if not already specified
- if not db_types:
- db_files = lib.helper.find_db_files()
- db_types = {}
- for db in db_files:
- with open(db, "r") as f:
- info = "".join(f.readlines())
- device_type = re.match("^.*SLOT;([\w]);DB;([-\w])+;.*", info)
- if device_type is None:
- log.fatal("Could not determine device type from: {}".format(info))
- exit(2)
- slot = device_type.group(1)
- db_type = device_type.group(2)
- db_types.update({slot: db_type})
- # Check if we have an implementation for the daughterboard types
- for db in db_types.values():
- try:
- getattr(lib.db, db)
- except AttributeError:
- log.fatal("Daughterboard class implementation for {} device not found!".format(db))
- exit(1)
- # Next steps
+ # Next steps implemented in periph_manager/derived class
#
# 1. Load FPGA image
# 2. Use motherboard and daughterboard types to load the FPGA image
diff --git a/mpm/python/usrp_mpm/rpc_server.py b/mpm/python/usrp_mpm/rpc_server.py
index b092abdf7..a5dda0826 100644
--- a/mpm/python/usrp_mpm/rpc_server.py
+++ b/mpm/python/usrp_mpm/rpc_server.py
@@ -61,7 +61,10 @@ class ClaimServer(RPCServer):
class MPMServer(RPCServer):
def __init__(self, state):
# Instead do self.mboard = periphs.init_periph_manager(args...)
- self.mboard = periphs.lib.n3xx.periph_manager("/dev/spidev1.0", "")
+ self.periph_manager = periphs.init_periph_manager()
+ # When we do init we can just add dboard/periph_manager methods with setattr(self, method)
+ # Maybe using partial
+ # To remove methods again we also have to remove them from self._methods dict (they're cached)
def get_clock_id(self, dboard):
dboard = getattr(self.mboard, "get_dboard_"+dboard)
diff --git a/mpm/python/usrp_mpm/types.py b/mpm/python/usrp_mpm/types.py
index bd7a874a8..31252e0b8 100644
--- a/mpm/python/usrp_mpm/types.py
+++ b/mpm/python/usrp_mpm/types.py
@@ -17,16 +17,18 @@
"""
MPM types
"""
+import ctypes
from multiprocessing import Value
from multiprocessing import Array
from multiprocessing import Lock
-import ctypes
+import struct
MPM_RPC_PORT = 49601
MPM_DISCOVERY_PORT = 49600
MPM_DISCOVERY_MESSAGE = "MPM-DISC"
+
class graceful_exit(Exception):
pass
@@ -36,3 +38,30 @@ class shared_state:
self.lock = Lock()
self.claim_status = Value(ctypes.c_bool, False, lock=self.lock) # lock
self.claim_token = Array(ctypes.c_char, 32, lock=self.lock) # String with max length of 32
+
+
+class eeprom(object):
+ # eeprom_header contains:
+ # 4 bytes magic
+ # 4 bytes CRC
+ # 2 bytes data_version
+ # 2 bytes hw_pid
+ # 2 bytes hw_rev
+ # 2 bytes pad
+ #
+ # 16 bytes in total
+ eeprom_header = struct.Struct("I I H H H 2x")
+
+ def read_eeprom(self, nvmem_path):
+ with open(nvmem_path, "rb") as f:
+ header = f.read(16)
+ data = f.read(240)
+ header = self.eeprom_header.unpack(header)
+ header = {
+ "magic": header[0],
+ "crc": header[1],
+ "data_version": header[2],
+ "hw_pid": header[3],
+ "hw_rev": header[4],
+ }
+ return (header, data)