aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py')
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py152
1 files changed, 152 insertions, 0 deletions
diff --git a/mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py b/mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py
new file mode 100644
index 000000000..f5e023229
--- /dev/null
+++ b/mpm/python/usrp_mpm/dboard_manager/x4xx_debug_db.py
@@ -0,0 +1,152 @@
+#
+# Copyright 2020 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Debug dboard implementation module
+"""
+
+from usrp_mpm.dboard_manager import DboardManagerBase
+from usrp_mpm.mpmlog import get_logger
+from usrp_mpm.sys_utils.gpio import Gpio
+
+class DebugDboardSignalPath:
+ def __init__(self, slot_idx, path, adc_indexes, dac_indexes, loopback):
+ self.log = get_logger("X4xxDebugDboard-{}-path-{}".format(slot_idx, path))
+
+ self.rxa2_led = Gpio("DB{}_RX{}2_LED".format(slot_idx, path), Gpio.OUTPUT, 0)
+ self.rxa_led = Gpio("DB{}_RX{}_LED".format(slot_idx, path), Gpio.OUTPUT, 0)
+ self.txa_led = Gpio("DB{}_TX{}_LED".format(slot_idx, path), Gpio.OUTPUT, 0)
+
+ self.trx_ctrl = Gpio("DB{}_TRX{}_CTRL".format(slot_idx, path), Gpio.OUTPUT, 0)
+ self.rx_mux_ctrl = Gpio("DB{}_RX{}_MUX_CTRL".format(slot_idx, path), Gpio.OUTPUT, 0)
+ self.tx_mux_ctrl = Gpio("DB{}_TX{}_MUX_CTRL".format(slot_idx, path), Gpio.OUTPUT, 0)
+
+ self._adc_indices = adc_indexes
+ self._dac_indices = dac_indexes
+ self._loopback = loopback
+ self._path = path
+
+ def configure(self, adc, dac, loopback):
+ """
+ Configure this path with the appropriate settings
+ """
+ if adc.lower() not in self._adc_indices:
+ error_msg = "Could not find ADC {} on path {}. Possible ADCs: {}".format(
+ adc, self._path, ", ".join(self._adc_indices.keys())
+ )
+ self.log.error(error_msg)
+ raise RuntimeError(error_msg)
+
+ if dac.lower() not in self._dac_indices:
+ error_msg = "Could not find DAC {} on path {}. Possible DACs: {}".format(
+ dac, self._path, ", ".join(self._dac_indices.keys())
+ )
+ self.log.error(error_msg)
+ raise RuntimeError(error_msg)
+
+ self.rx_mux_ctrl.set(self._adc_indices[adc.lower()])
+ self.tx_mux_ctrl.set(self._dac_indices[dac.lower()])
+ self.trx_ctrl.set(self._loopback if loopback else not self._loopback)
+
+
+class X4xxDebugDboard(DboardManagerBase):
+ """
+ Holds all dboard specific information and methods of the X4xx debug dboard
+ """
+ #########################################################################
+ # Overridables
+ #
+ # See DboardManagerBase for documentation on these fields
+ #########################################################################
+ pids = [0x4001]
+ ### End of overridables #################################################
+
+ def __init__(self, slot_idx, **kwargs):
+ DboardManagerBase.__init__(self, slot_idx, **kwargs)
+ self.log = get_logger("X4xxDebugDboard-{}".format(slot_idx))
+ self.log.trace("Initializing X4xxDebug daughterboard, slot index %d",
+ self.slot_idx)
+
+ # Interface with MB HW
+ if 'db_iface' not in kwargs:
+ self.log.error("Required DB Iface was not provided!")
+ raise RuntimeError("Required DB Iface was not provided!")
+ self.db_iface = kwargs['db_iface']
+
+ # Power on the card
+ self.db_iface.enable_daughterboard(enable=True)
+ if not self.db_iface.check_enable_daughterboard():
+ self.db_iface.enable_daughterboard(enable=False)
+ self.log.error('Debug dboard {} power up failed'.format(self.slot_idx))
+ raise RuntimeError('Debug dboard {} power up failed'.format(self.slot_idx))
+
+ self._paths = {
+ "a": DebugDboardSignalPath(
+ slot_idx,
+ "A",
+ {
+ "adc0": 1,
+ "adc2": 0,
+ },
+ {
+ "dac0": 1,
+ "dac2": 0,
+ },
+ 1 # TRXA_CTRL=1 enables loopback
+ ),
+ "b": DebugDboardSignalPath(
+ slot_idx,
+ "B",
+ {
+ "adc3": 1,
+ "adc1": 0,
+ },
+ {
+ "dac3": 1,
+ "dac1": 0,
+ },
+ 0 # TRXB_CTRL=0 enables loopback
+ ),
+ }
+
+
+ # TODO: Configure the correct RFDC settings for this board
+ #if not self.db_iface.disable_mixer():
+ # raise RuntimeError("Received an error disabling the mixer for slot_idx={}".format(slot_idx))
+
+ def init(self, args):
+ """
+ Execute necessary init dance to bring up dboard
+ """
+ self.log.debug("init() called with args `{}'".format(
+ ",".join(['{}={}'.format(x, args[x]) for x in args])
+ ))
+ self.config_path("a", "adc0", "dac0", 0)
+ self.config_path("b", "adc1", "dac1", 0)
+ return True
+
+ def deinit(self):
+ pass
+
+ def tear_down(self):
+ self.db_iface.tear_down()
+
+ def config_path(self, path, adc, dac, loopback):
+ """
+ Configure the signal paths on the daughterboard.
+ path - Select between front panel connectors A or B. The two paths are unconnected.
+ adc - Select which ADC to connect to the path (adc0 or adc2 on A, adc1 or adc3 on B)
+ dac - Select which DAC to connect to the path (dac0 or dac2 on A, dac1 or dac3 on B)
+ loopback - Whether to enable loopback (1) or route the ADC/DACs to the front panel (0)
+
+ Example MPM shell usage:
+ > db_0_config_path a adc0 dac2 1
+ """
+ if path.lower() not in self._paths:
+ self.log.error("Tried to configure path {} which does not exist!".format(path))
+ raise RuntimeError("Tried to configure path {} which does not exist!".format(path))
+
+ path = self._paths[path.lower()]
+ path.configure(adc, dac, int(loopback))