mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
Co-authored-by: Lars Amsel <lars.amsel@ni.com> Co-authored-by: Michael Auchter <michael.auchter@ni.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Cristina Fuentes <cristina.fuentes-curiel@ni.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Virendra Kakade <virendra.kakade@ni.com> Co-authored-by: Lane Kolbly <lane.kolbly@ni.com> Co-authored-by: Max Köhler <max.koehler@ni.com> Co-authored-by: Andrew Lynch <andrew.lynch@ni.com> Co-authored-by: Grant Meyerhoff <grant.meyerhoff@ni.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Thomas Vogel <thomas.vogel@ni.com>
152 lines
5.7 KiB
Python
152 lines
5.7 KiB
Python
#
|
|
# 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))
|