File: x4xx_if_test_cca.py

package info (click to toggle)
uhd 4.9.0.0%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 184,180 kB
  • sloc: cpp: 262,887; python: 112,011; ansic: 102,670; vhdl: 57,031; tcl: 19,924; xml: 8,581; makefile: 3,028; sh: 2,812; pascal: 230; javascript: 120; csh: 94; asm: 20; perl: 11
file content (167 lines) | stat: -rw-r--r-- 6,667 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#
# Copyright 2020 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
"""
IF Test CCA 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 X4xxIfTestCCA(DboardManagerBase):
    """
    Holds all dboard specific information and methods of the X4xx IF Test CCA
    """
    #########################################################################
    # Overridables
    #
    # See DboardManagerBase for documentation on these fields
    #########################################################################
    pids = [0x4006]
    ### End of overridables #################################################

    def __init__(self, slot_idx, **kwargs):
        DboardManagerBase.__init__(self, slot_idx, **kwargs)
        self.log = get_logger("X4xxIfTestCCA-{}".format(slot_idx))
        self.log.trace("Initializing X4xxIfTestCCA, 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('IF Test CCA {} power up failed'.format(self.slot_idx))
            raise RuntimeError('IF Test CCA {} power up failed'.format(self.slot_idx))

        # [boolean for stage 1 mux , boolean for stage 2 mux]
        self._adc_mux_settings = {
            "adc0" : [0, 0],
            "adc1" : [1, 1],
            "adc2" : [1, 0],
            "adc3" : [0, 1],
        }

        self._dac_mux_settings = {
            "dac0" : [1, 0],
            "dac1" : [1, 1],
            "dac2" : [0, 0],
            "dac3" : [0, 1],
        }

        # There are 4 possible Tx (DAC) streams that are available to choose
        # to export to the SMA TX port using a 2-stage hardware mux.

        # Choose between 0 and 2 OR 1 and 3
        self.tx_0_2_1_3_mux_ctrl = Gpio("DB{}_TX0_2p_1_3n".format(slot_idx), Gpio.OUTPUT, 0)
        # Choose between 0 OR 2
        self.tx_0_2_mux_ctrl = Gpio("DB{}_TX_MUX_0p_2n".format(slot_idx), Gpio.OUTPUT, 0)
        # Choose between 1 OR 3
        self.tx_1_3_mux_ctrl = Gpio("DB{}_TX_MUX_1p_3n".format(slot_idx), Gpio.OUTPUT, 0)

        # The signal from the SMA RX port can be directed to one of the 4
        # available Rx (ADC) streams using a 2-stage hardware mux.

        # Choose between 0 and 2 OR 1 and 3
        self.rx_0_2_1_3_mux_ctrl = Gpio("DB{}_RX0_2p_1_3n".format(slot_idx), Gpio.OUTPUT, 0)
        # Choose between 0 OR 2
        self.rx_0_2_mux_ctrl = Gpio("DB{}_RX_MUX_0p_2n".format(slot_idx), Gpio.OUTPUT, 0)
        # Choose between 1 OR 3
        self.rx_1_3_mux_ctrl = Gpio("DB{}_RX_MUX_1p_3n".format(slot_idx), Gpio.OUTPUT, 0)

        self._tx_path = ""
        self._rx_path = ""

        # Controls to load the power supplies on the daughterboard. Enabling
        # these will increase the power draw of the daughterboard.
        self.enable_1v8_load = Gpio("DB{}_1V8_LOAD".format(slot_idx), Gpio.OUTPUT, 0)
        self.enable_2v5_load = Gpio("DB{}_2V5_LOAD".format(slot_idx), Gpio.OUTPUT, 0)
        self.enable_3v3_load = Gpio("DB{}_3V3_LOAD".format(slot_idx), Gpio.OUTPUT, 0)
        self.enable_3v3_mcu_load = Gpio("DB{}_3V3_MCU_LOAD".format(slot_idx), Gpio.OUTPUT, 0)
        self.enable_3v7_load = Gpio("DB{}_3V7_LOAD".format(slot_idx), Gpio.OUTPUT, 0)
        self.enable_12v_load = Gpio("DB{}_12V_LOAD".format(slot_idx), Gpio.OUTPUT, 0)

        # Control to choose between DAC output or MB VCM signals as the VCM
        # signal to use on board.
        self.disable_vcm_dac = Gpio("DB{}_VCM_MB_nDAC".format(slot_idx), Gpio.OUTPUT, 0)

        # Control to choose which MB clock to output to the SMA Clock port.
        # Choices are BaseRefClk and PllRefClk
        self.disable_vcm_dac = Gpio("DB{}_REF_CLK_SEL_USR".format(slot_idx), Gpio.OUTPUT, 0)


    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_tx_path("dac0")
        self.config_rx_path("adc0")
        return True

    def deinit(self):
        pass

    def tear_down(self):
        self.db_iface.tear_down()

    def config_tx_path(self, dac):
        """
        Configure the tx signal path on the daughterboard.
        dac - Select which DAC to connect to the Tx path (dac0 through dac3)

        Example MPM shell usage:
        > db_0_config_tx_path dac2
        """

        if dac.lower() not in self._dac_mux_settings:
            error_msg = "Could not find DAC {}. Possible DACs: {}".format(
                dac, ", ".join(self._dac_mux_settings.keys())
            )
            self.log.error(error_msg)
            raise RuntimeError(error_msg)

        # Only one of the following setting really matters; simplify logic
        # by toggling both since the stage 2 decides what gets connected.
        self.tx_0_2_mux_ctrl.set(self._dac_mux_settings[dac.lower()][0])
        self.tx_1_3_mux_ctrl.set(self._dac_mux_settings[dac.lower()][0])
        self.tx_0_2_1_3_mux_ctrl.set(self._dac_mux_settings[dac.lower()][1])
        self._tx_path = dac.upper()

    def get_tx_path(self):
        return self._tx_path

    def config_rx_path(self, adc):
        """
        Configure the rx signal path on the daughterboard.
        adc - Select which ADC to connect to the Rx path (adc0 through adc3)

        Example MPM shell usage:
        > db_0_config_rx_path adc0
        """

        if adc.lower() not in self._adc_mux_settings:
            error_msg = "Could not find ADC {}. Possible ADCs: {}".format(
                adc, ", ".join(self._adc_mux_settings.keys())
            )
            self.log.error(error_msg)
            raise RuntimeError(error_msg)

        self.rx_0_2_1_3_mux_ctrl.set(self._adc_mux_settings[adc.lower()][1])
        # Only one of the following setting really matters; simplify logic
        # by toggling both
        self.rx_0_2_mux_ctrl.set(self._adc_mux_settings[adc.lower()][0])
        self.rx_1_3_mux_ctrl.set(self._adc_mux_settings[adc.lower()][0])
        self._rx_path = adc.upper()

    def get_rx_path(self):
        return self._rx_path