diff options
| author | Andrej Rode <andrej.rode@ettus.com> | 2017-03-21 19:46:50 -0700 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:03:44 -0800 | 
| commit | ef6326a174e6880be5e2eaeac26a2c5de0768807 (patch) | |
| tree | c949545e02390745c3a373e657bcf2404e62e191 /mpm/python | |
| parent | b29246a9e2d7ed1e03e44cfc6804615fcfa5a5d8 (diff) | |
| download | uhd-ef6326a174e6880be5e2eaeac26a2c5de0768807.tar.gz uhd-ef6326a174e6880be5e2eaeac26a2c5de0768807.tar.bz2 uhd-ef6326a174e6880be5e2eaeac26a2c5de0768807.zip  | |
mpm: python refactoring
Diffstat (limited to 'mpm/python')
26 files changed, 613 insertions, 139 deletions
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)  | 
