diff options
Diffstat (limited to 'mpm/python/usrp_mpm')
-rw-r--r-- | mpm/python/usrp_mpm/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/__init__.py | 2 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/__init__.py | 28 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/base.py | 37 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/eiscat.py | 31 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 50 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/unknown.py | 32 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/helper.py | 3 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/__init__.py | 29 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/base.py | 75 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periph_manager/n310.py | 46 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/periphs.py | 47 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/rpc_server.py | 5 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/types.py | 31 |
14 files changed, 376 insertions, 42 deletions
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) |