Reference Rx Operator

This Python example runs on PC and controls an N1010A FlexDCA application. The script installs a Reference Rx operator and, in Eye mode, returns TDECQ measurement. The script demonstrates the addressing of commands to the correct waveform function numbers.

Copy

Reference-Rx-operator.py

""" Script on PC controls N1010A FlexDCA application. The script installs
a Reference Rx operator and, in Eye mode, returns TDECQ measurement.
Demonstrates the addressing of commands to the correct waveform function numbers.
"""

import pyvisa as visa  # import VISA library

visa_address = 'TCPIP0::localhost::hislip0,4880::INSTR'

def open_flexdca_connection(address):
    """ Opens visa connection to FlexFlexDCA. """
    print('Connecting to Flexdca ...')
    try:
        rm = visa.ResourceManager()
        connection = rm.open_resource(address)
        connection.timeout = 10000  # Set connection timeout to 10s
        connection.read_termination = '\n'
        connection.write_termination = '\n'
        inst_id = connection.query('*IDN?')
        print('\nFlexDCA connection established to:\n' + inst_id, flush=True)
        connection.query(':SYSTem:DEFault;*OPC?')
    except (visa.VisaIOError, visa.InvalidSession):
        print('\nVISA ERROR: Cannot open instrument address.\n', flush=True)
        return None
    except Exception as other:
        print('\nVISA ERROR: Cannot connect to instrument:', other, flush=True)
        print('\n')
        return None
    return connection


def all_channels_off(FlexDCA):
    """ Turns all available channels off. """
    
    for slot in '12345678':
        for letter in 'ABCD':
            channel = slot + letter
            FlexDCA.write(':CHANnel' + channel + ':DISPlay OFF')
    
    
def install_simulated_module(FlexDCA):
    """ Install a dual-optical simulated FlexDCA module. """
    
    FlexDCA.write(':EMODules:SLOT1:SELection DOMini')
    all_channels_off(flexdca)
    FlexDCA.write(':SOURce1A:FORMat PAM4')
    FlexDCA.write(':SOURce1A:WTYPe DATA')
    FlexDCA.write(':SOURce1A:PATTern EPRBs15')
    FlexDCA.write(':SOURce1A:SRATe 2.890000000E+10')
    FlexDCA.write(':SOURce1A:AMPLitude 20E-3')
    FlexDCA.write(':SOURce1A:NOISe:RN 2.50E-7')
    FlexDCA.write(':SOURce1A:JITTer:RJ 1.0E-12')
    FlexDCA.write(':CHANnel1A:DISPlay ON')
    FlexDCA.write(':ACQuire:RUN')
    FlexDCA.query(':SYSTem:MODE EYE;*OPC?')
    FlexDCA.query(':TRIGger:PLOCk ON;*OPC?')
    FlexDCA.query(':SYSTem:AUToscale;*OPC?')


def install_Ref_Rx_operator(FlexDCA):
    """ Installs Reference Rx operator and CTLE secondary operator. Displays the waveforms.
    TDECQ and DFE equalizers are installed by default.
    :SPRocess commands addressed to Reference Rx (F1)
    :FUNCtion commands addressed to CTLE (F2), TDECQ (F3), DFE (F4)
    """

    FlexDCA.write(':FUNCtion1:FOPerator RRX')
    FlexDCA.write(':SPRocess1:RRX:SIFunctions ON')  # show secondary operators
    FlexDCA.write(':FUNCtion1:SOP2 CTLequalizer')  # install secondary CTLE equalizer
    FlexDCA.write(':FUNCtion1:COLor TCOLor3')  # Display Function 1 (Ref Rx waveform)
    FlexDCA.write(':FUNCtion1:DISPlay ON')
    FlexDCA.write(':FUNCtion2:COLor TCOLor4')  # Display Function 2 (CTLE waveform)
    FlexDCA.write(':FUNCtion2:DISPlay ON')
    FlexDCA.write(':FUNCtion3:COLor TCOLor6')  # Display Function 3 (TDECQ waveform)
    FlexDCA.write(':FUNCtion3:DISPlay ON')
    FlexDCA.write(':FUNCtion4:COLor TCOLor7')  # Display Function 4 (DFE waveform)
    FlexDCA.write(':FUNCtion4:DISPlay ON')
    FlexDCA.write(':DISPlay:WINDow:TIME1:DMODe STILed')
    

def config_Ref_Rx(FlexDCA):
""" :SPRocess commands addressed to Reference Rx (F1) """

    FlexDCA.write(':SPRocess1:RRX:PROPtimize ON')
    FlexDCA.write(':SPRocess1:RRX:RPOint ASOP2')


def config_Secondary_CTLE(FlexDCA):
    """ :SPRocess commands addressed to Reference Rx (F1)
    :FUNCtion commands addressed to CTLE (F2)
    """
    
    FlexDCA.write(':SPRocess1:CTLequalizer:ZERo1 4.200E+9')
    FlexDCA.write(':FUNCtion2:VTRacking MANual')
    FlexDCA.write(':FUNCtion2:YSCale 4.5E-3')


def config_Secondary_TDECQ(FlexDCA):
    """ :SPRocess commands addressed to Reference Rx (F1) """

    FlexDCA.write(':SPRocess1:TEQualizer:FIBer:ENABle ON')
    FlexDCA.write(':SPRocess1:TEQualizer:FIBer:BANDwidth 2.96E+10')
    FlexDCA.write(':MEASure:TDEQ:TSER 4.50E-4')


def config_Secondary_DFE(FlexDCA):
    """ :SPRocess commands addressed to Reference Rx (F1) """
    
    FlexDCA.write(':SPRocess1:DFEQualizer:PROPtimize:LTMagnitudes ON')
    FlexDCA.write(':SPRocess1:DFEQualizer:PROPtimize:BMAX 4.1E-1, 3.5E-1, 1.2E-1, 1.0E-1')
    FlexDCA.write(':SPRocess1:DFEQualizer:TAPS:AUTo OFF')
    FlexDCA.write(':SPRocess1:DFEQualizer:PROPtimize:TAPS 2.7043E-2, 7.5E-5, -1.8686E-2, -9.465E-3')


def measure_tdecq(FlexDCA):
    """ Returns a scalar TDECQ measurement result. """
    
    import time
    
    class ScalarMeasQuestionableException(Exception):
        """ A scalar measurement result is questionable. """
        pass
    
    class ScalarMeasTimeOutException(Exception):
        """ A scalar measurement has timed out. """
        pass
    
    timeout = FlexDCA.timeout / 1000  # convert ms to s
    start_time = time.time()  # time in seconds
    flexdca.write(':MEAS:EYE:TDEQ')
    while(True):
        time.sleep(0.2)
        status = FlexDCA.query(':MEAS:EYE:TDEQ:STATus?')
        if 'CORR' in status:  # valid measurement result
            return FlexDCA.query(':MEAS:EYE:TDEQ?')  # get measurement
        elif 'QUES' in status:  # questionable results
            s = ':MEAS:EYE:TDEQ\nReason: ' + FlexDCA.query(':MEAS:EYE:TDEQ:STATus:REASon?')
            raise ScalarMeasQuestionableException(s)
        elif (int(time.time() - start_time)) > timeout:  # IO timout
            s = ':MEAS:EYE:TDEQ\nReason: ' + FlexDCA.query(':MEAS:EYE:TDEQ:STATus:REASon?')
            raise ScalarMeasTimeOutException(s)


flexdca = open_flexdca_connection(visa_address)
install_simulated_module(flexdca)
install_Ref_Rx_operator(flexdca)
config_Ref_Rx(flexdca)
config_Secondary_CTLE(flexdca)
config_Secondary_TDECQ(flexdca)
config_Secondary_DFE(flexdca)
flexdca.write(':SPRocess1:RRX:RECalculate')
tdecq = measure_tdecq(flexdca)
print('TDECQ measures: ' + tdecq + ' dB')
flexdca.write(':SYSTem:GTLocal')
flexdca.close()