diff options
Diffstat (limited to 'mpm/python')
| -rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/neon.py | 70 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e320.py | 77 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/periph_manager/e320_periphs.py | 31 | 
3 files changed, 148 insertions, 30 deletions
| diff --git a/mpm/python/usrp_mpm/dboard_manager/neon.py b/mpm/python/usrp_mpm/dboard_manager/neon.py index e3797c7d3..5ab014330 100644 --- a/mpm/python/usrp_mpm/dboard_manager/neon.py +++ b/mpm/python/usrp_mpm/dboard_manager/neon.py @@ -17,6 +17,7 @@ from usrp_mpm.dboard_manager import DboardManagerBase  from usrp_mpm.mpmlog import get_logger  from usrp_mpm.sys_utils.udev import get_eeprom_paths  from usrp_mpm.sys_utils.uio import UIO +from usrp_mpm.periph_manager.e320_periphs import MboardRegsControl  ############################################################################### @@ -34,6 +35,8 @@ class Neon(DboardManagerBase):      pids = [0xe320]      rx_sensor_callback_map = {          'ad9361_temperature': 'get_catalina_temp_sensor', +        'rssi' : 'get_rssi_sensor', +        'lo_lock' : 'get_lo_lock_sensor',      }      tx_sensor_callback_map = {          'ad9361_temperature': 'get_catalina_temp_sensor', @@ -258,24 +261,65 @@ class Neon(DboardManagerBase):      ##########################################################################      # Sensors      ########################################################################## -    # TODO add sensors      def get_ad9361_lo_lock(self, which):          """          Return LO lock status (Boolean!) of AD9361. 'which' must be          either 'tx' or 'rx'          """ -        # return self.catalina. +        self.mboard_regs_label = "mboard-regs" +        self.mboard_regs_control = MboardRegsControl( +            self.mboard_regs_label, self.log) +        if which == "tx": +            locked = self. mboard_regs_control.get_ad9361_tx_lo_lock() +        elif which == "rx": +            locked = self. mboard_regs_control.get_ad9361_rx_lo_lock() +        else: +            locked = False +        return locked -        # uhd::sensor_value_t e300_impl::_get_fe_pll_lock(const bool is_tx) -        # { -        #     const uint32_t st = -        #         _global_regs->peek32(global_regs::RB32_CORE_PLL); -        #     const bool locked = is_tx ? ((st & 0x1) > 0) : ((st & 0x2) > 0); -        #     return sensor_value_t("LO", locked, "locked", "unlocked"); -        # } -        #return self.mykonos.get_lo_locked(which.upper()) -        #FIXME: Implement on RevB -        time.sleep(5) -        return True +    def get_lo_lock_sensor(self, which): +        """ +        Get sensor dict with LO lock status +        """ +        self.log.trace("Reading LO Lock.") +        lo_locked = self.get_ad9361_lo_lock(which) +        return { +            'name': 'ad9361_lock', +            'type': 'BOOLEAN', +           'unit': 'locked' if lo_locked else 'unlocked', +           'value': str(lo_locked).lower(), +        } +    def get_catalina_temp_sensor(self, _): +        """ +        Get temperature sensor reading of Catalina. +        """ +        # Note: the unused argument is channel +        self.log.trace("Reading Catalina temperature.") +        return { +            'name': 'ad9361_temperature', +            'type': 'REALNUM', +            'unit': 'C', +            'value': str(self.catalina.get_temperature()) +        } + +    def get_rssi_val(self, which): +        """ +        Return the current RSSI of `which` chain in Catalina +        """ +        return self.catalina.get_rssi(which) + +    def get_rssi_sensor(self, which=None): +        """ +        Return a sensor dictionary containing the current RSSI of `which` chain in Catalina +        """ +        if which is None: +            # Default to RX1 chain +            which = "RX1" +        return { +            'name': 'rssi', +            'type': 'REALNUM', +            'unit': 'dB', +            'value': str(self.get_rssi_val(which)), +        } diff --git a/mpm/python/usrp_mpm/periph_manager/e320.py b/mpm/python/usrp_mpm/periph_manager/e320.py index ac50909ff..848b320b0 100644 --- a/mpm/python/usrp_mpm/periph_manager/e320.py +++ b/mpm/python/usrp_mpm/periph_manager/e320.py @@ -10,15 +10,18 @@ E320 implementation module  from __future__ import print_function  import bisect  import copy +import re  import threading  from six import iteritems, itervalues  from usrp_mpm.components import ZynqComponents  from usrp_mpm.dboard_manager import Neon +from usrp_mpm.gpsd_iface import GPSDIfaceExtension  from usrp_mpm.mpmtypes import SID  from usrp_mpm.mpmutils import assert_compat_number, str2bool  from usrp_mpm.periph_manager import PeriphManagerBase  from usrp_mpm.rpc_server import no_rpc  from usrp_mpm.sys_utils import dtoverlay +from usrp_mpm.sys_utils.sysfs_thermal import read_thermal_sensor_value  from usrp_mpm.sys_utils.udev import get_spidev_nodes  from usrp_mpm.xports import XportMgrUDP, XportMgrLiberio  from usrp_mpm.periph_manager.e320_periphs import MboardRegsControl @@ -77,7 +80,9 @@ class e320(ZynqComponents, PeriphManagerBase):                    }      mboard_max_rev = 2  # RevB      mboard_sensor_callback_map = { -        # FIXME add sensors +        'gps_locked': 'get_gps_lock_sensor', +        'temp': 'get_temp_sensor', +        'fan': 'get_fan_sensor',      }      max_num_dboards = 1      crossbar_base_port = 2  # It's 2 because 0,1 are SFP,DMA @@ -129,6 +134,7 @@ class e320(ZynqComponents, PeriphManagerBase):          self._clock_source = None          self._time_source = None          self._available_endpoints = list(range(256)) +        self._gpsd = None          self.dboard = self.dboards[E320_DBOARD_SLOT_IDX]          try:              self._init_peripherals(args) @@ -264,6 +270,8 @@ class e320(ZynqComponents, PeriphManagerBase):          )          # Init clocking          self._init_ref_clock_and_time(args) +        # Init GPSd iface and GPS sensors +        self._init_gps_sensors()          # Init CHDR transports          self._xport_mgrs = {              'udp': E320XportMgrUDP(self.log.getChild('UDP')), @@ -280,6 +288,22 @@ class e320(ZynqComponents, PeriphManagerBase):          # Init complete.          self.log.debug("mboard info: {}".format(self.mboard_info)) +    def _init_gps_sensors(self): +        "Init and register the GPSd Iface and related sensor functions" +        self.log.trace("Initializing GPSd interface") +        self._gpsd = GPSDIfaceExtension() +        new_methods = self._gpsd.extend(self) +        for method_name in new_methods: +            try: +                # Extract the sensor name from the getter +                sensor_name = re.search(r"get_.*_sensor", method_name).string +                # Register it with the MB sensor framework +                self.mboard_sensor_callback_map[sensor_name] = method_name +                self.log.trace("Adding %s sensor function", sensor_name) +            except AttributeError: +                # re.search will return None is if can't find the sensor name +                self.log.warning("Error while registering sensor function: %s", method_name) +      ###########################################################################      # Session init and deinit      ########################################################################### @@ -571,27 +595,46 @@ class e320(ZynqComponents, PeriphManagerBase):          """          Get temperature sensor reading of the E320.          """ -        # TODO: This is Catalina's temperature. Do we want to return a different temp? -        return self.catalina.get_temperature() +        self.log.trace("Reading FPGA temperature.") +        return_val = '-1' +        try: +            raw_val = read_thermal_sensor_value('fpga-thermal-zone', 'temp') +            return_val = str(raw_val / 1000) +        except ValueError: +            self.log.warning("Error when converting temperature value") +        except KeyError: +            self.log.warning("Can't read temp on fpga-thermal-zone") +        return { +            'name': 'temperature', +            'type': 'REALNUM', +            'unit': 'C', +            'value': return_val +        }      def get_gps_lock_sensor(self):          """          Get lock status of GPS as a sensor dict          """ -        self.log.trace("Reading status GPS lock pin from port expander") -        raise NotImplementedError("GPS lock not implemented") -        # FIXME put it in a register -        # TODO: implement get_gps_lock, splits up functionality -        #gps_locked = bool(self._gpios.get("GPS-LOCKOK")) -        #return { -        #    'name': 'gps_lock', -        #    'type': 'BOOLEAN', -        #    'unit': 'locked' if gps_locked else 'unlocked', -        #    'value': str(gps_locked).lower(), -        #} - -    # TODO: Add other GPS sensors (time, TPV, SKY, etc.) -    # TODO: Add all physical sensors we can +        gps_locked = self.mboard_regs_control.get_gps_locked_val() +        return { +            'name': 'gps_lock', +            'type': 'BOOLEAN', +            'unit': 'locked' if gps_locked else 'unlocked', +            'value': str(gps_locked).lower(), +        } + +    def get_fan_sensor(self): +        """ +        Return a sensor dictionary containing the RPM of the fan +        """ +        raise NotImplementedError("Fan sensor not implemented") +        # TODO implement +        # return { +        #     'name': 'rssi', +        #     'type': 'REALNUM', +        #     'unit': 'rpm', +        #     'value': XX, +        # }      ###########################################################################      # EEPROMs diff --git a/mpm/python/usrp_mpm/periph_manager/e320_periphs.py b/mpm/python/usrp_mpm/periph_manager/e320_periphs.py index d98c5a0e5..ee092e248 100644 --- a/mpm/python/usrp_mpm/periph_manager/e320_periphs.py +++ b/mpm/python/usrp_mpm/periph_manager/e320_periphs.py @@ -94,6 +94,10 @@ class MboardRegsControl(object):      MB_DBOARD_CTRL_MIMO = 0      MB_DBOARD_CTRL_TX_CHAN_SEL = 1 +    # Bitfield locations for the MB_DBOARD_STATUS register. +    MB_DBOARD_STATUS_RX_LOCK = 6 +    MB_DBOARD_STATUS_TX_LOCK = 7 +      def __init__(self, label, log):          self.log = log          self.regs = UIO( @@ -381,3 +385,30 @@ class MboardRegsControl(object):              self.log.trace("Writing MB_DBOARD_CTRL to 0x{:08X}".format(reg_val))              self.poke32(self.MB_DBOARD_CTRL, reg_val) +    def get_ad9361_tx_lo_lock(self): +        """ +        Check the status of TX LO lock from CTRL_OUT pins from Catalina +        """ +        mask = 0b1 << self.MB_DBOARD_STATUS_TX_LOCK +        with self.regs.open(): +            reg_val =  self.peek32(self.MB_DBOARD_STATUS) +        locked = (reg_val & mask) > 0 +        if not locked: +            self.log.warning("TX RF PLL reporting unlocked. ") +        else: +            self.log.trace("TX RF PLL locked") +        return locked + +    def get_ad9361_rx_lo_lock(self): +        """ +        Check the status of RX LO lock from CTRL_OUT pins from Catalina +        """ +        mask = 0b1 << self.MB_DBOARD_STATUS_RX_LOCK +        with self.regs.open(): +            reg_val =  self.peek32(self.MB_DBOARD_STATUS) +        locked = (reg_val & mask) > 0 +        if not locked: +            self.log.warning("RX RF PLL reporting unlocked. ") +        else: +            self.log.trace("RX RF PLL locked") +        return locked | 
