# Jitter Measurements

This simple Python script, measure-jitter.py, makes some Jitter measurements.

## Script

measure-jitter.py

    #!python3

    """This program illustrates making Jitter measurements in
    the Infiniium XR8 oscilloscope.
    """

    # Import modules.
    import pyvisa
    import sys
    from matplotlib.ticker import EngFormatter

    # Global variables.
    oscilloscope_visa_address = "TCPIP0::localhost::hislip0,4880::INSTR"
    timeout = 20000  # 20 seconds.
    eng_s = EngFormatter(unit="s", places=2, sep=" ")
    eng_V = EngFormatter(unit="V", places=2, sep=" ")

    # Files location.
    standard_folder = "C:\\Users\\pw5670\\Documents\\Keysight\\Infiniium\\"

    def exit_program():
        """Exit program."""

        # Close connection to oscilloscope.
        sys.stdout.write("Closing oscilloscope connection.\n")
        Infiniium.write(":SYSTem:GTLocal")  # Unlock GUI.
        Infiniium.clear()  # Clear oscilloscope communications interface.
        Infiniium.close()  # Close communications interface to oscilloscope.
        rm.close()  # Close resource manager.
        print("End of program.")
        sys.exit()

    def check_error_queue(when):
        """Check error queue."""

        errors_found = False
        while True:
            # Keep reading errors until "No error".
            error_string = Infiniium.query(":SYSTem:ERRor:NEXT? DIAGnostic")
            if error_string:  # If there is an error string value.

                if error_string.find("0,", 0, 2) == -1:  # Not "No error".
                    errors_found = True
                    print(f"ERROR: {error_string}")

                else:  # "No error"
                    break

            else:  # :SYSTem:ERRor:NEXT? DIAGnostic should always return string.
                errors_found = True
                print("ERROR: :SYSTem:ERRor:NEXT? DIAGnostic returned nothing.")
                break

        if errors_found:
            print(f"Exited because error(s) found when: '{when}'")
            exit_program()

    # ==========================================================
    # Main program:
    # ==========================================================

    # Connect and initialize oscilloscope.
    rm = pyvisa.ResourceManager("C:\\Windows\\System32\\visa64.dll")
    try:
        Infiniium = rm.open_resource(oscilloscope_visa_address)
    except Exception:
        print(
            f"Unable to connect to oscilloscope at {oscilloscope_visa_address}. Aborting program."
        )
        sys.exit()

    Infiniium.timeout = timeout  # Set global timeout.
    Infiniium.clear()  # Clear the instrument bus.
    # Lock GUI happens automatically.

    # Move waveform file to oscilloscope disk.
    wfm_data_file = "Jitter_Noise.h5"
    wfm_data_file_local = f"../{wfm_data_file}"
    wfm_data_file_osc = f"{standard_folder}{wfm_data_file}"
    f = open(wfm_data_file_local, "rb")
    file_bytes = f.read()
    f.close()
    message = f':DISK:FILE:WRITe? "{wfm_data_file_osc}",'
    Infiniium.write_binary_values(message, file_bytes, datatype="s")
    success_or_failure = Infiniium.read().strip()
    if success_or_failure == "1":
        print(f"Local file copied to oscilloscope disk: {wfm_data_file_osc}")
    else:
        print(f"FAILURE copying local file to oscilloscope disk: {wfm_data_file_osc}")

    # Default Setup.
    print("Default Setup.")
    Infiniium.write(":SYSTem:DEFault")

    # Stop acquisitions and clear the display.
    Infiniium.write(":ACQuire:STOP")
    Infiniium.write(":ACQuire:CDISplay")

    # Load waveform data from oscilloscope disk into waveform memory.
    Infiniium.write(f':WMEMory1:FILE:NAME "{wfm_data_file_osc}"')
    Infiniium.write(":WMEMory1:FILE:LOAD")
    print(f"Waveform data loaded from oscilloscope disk: {wfm_data_file_osc}")

    # Turn off channel 1.
    Infiniium.write(":CHANnel1:DISPlay OFF")

    # Make jitter measurements.
    Infiniium.write(":MEASure:JITTer1:JITTer:RJBandwidth NARRow")
    Infiniium.write(":MEASure:JITTer1:JITTer:TJBer 1E-12")
    Infiniium.write(":MEASure:JITTer1:JITTer:EDGE BOTH")
    Infiniium.write(":MEASure:JITTer1:JITTer:SMEThod SPECtral")
    Infiniium.write(":MEASure:JITTer1:JITTer:MODE TPHase")
    Infiniium.write(":MEASure:JITTer1:JITTer:EOPening SER")
    Infiniium.write(":MEASure:JITTer1:JITTer:PTYPe PERiodic")
    Infiniium.write(":MEASure:JITTer1:SOURce WMEMory1")
    Infiniium.write(":MEASure:JITTer1:JITTer:UNITs SECond")

    jitter_results_dict = {}
    Infiniium.write(f":MEASure:JITTer1:JITTer:ANALysis ON")
    jitter_measurements = ["EWIDth", "TJ"]
    for meas in jitter_measurements:
        result = float(Infiniium.query(f":MEASure:JITTer1:JITTer:{meas}?"))
        status = Infiniium.query(f":MEASure:JITTer1:JITTer:{meas}:STATus?").strip()
        reason = Infiniium.query(f":MEASure:JITTer1:JITTer:{meas}:STATus:REASon?").strip()
        jitter_results_dict[meas] = (result, status, reason)

    # Make noise measurements.
    Infiniium.write(":MEASure:JITTer:NOISe:RNBandwidth WIDE")
    Infiniium.write(":MEASure:JITTer:NOISe:MLOCation 50")
    Infiniium.write(":MEASure:JITTer:NOISe:UNITs VOLT")

    noise_results_dict = {}
    Infiniium.write(f":MEASure:JITTer1:NOISe:ANALysis ON")
    noise_measurements = [
        ["EHEight", ""],
        ["TI", "LEVel1"],
        ["TI", "LEVel0"],
    ]
    for meas, level in noise_measurements:
        if level != "":
            Infiniium.write(f":MEASure:JITTer1:NOISe:{meas}:LEVel {level}")
        result = float(Infiniium.query(f":MEASure:JITTer1:NOISe:{meas}?"))
        status = Infiniium.query(f":MEASure:JITTer1:NOISe:{meas}:STATus?").strip()
        reason = Infiniium.query(f":MEASure:JITTer1:NOISe:{meas}:STATus:REASon?").strip()
        noise_results_dict[(meas, level)] = (result, status, reason)

    # Print selected results.
    print("Jitter measurement results:")
    for meas in jitter_measurements:
        (result, status, reason) = jitter_results_dict[meas]
        if status != "CORR":
            print(f"{meas}: {eng_s(result)}, status: {status}, reason: {reason}")
        else:
            print(f"{meas}: {eng_s(result)}")

    print("Noise measurement results:")
    for meas, level in noise_measurements:
        (result, status, reason) = noise_results_dict[(meas, level)]
        if level != "":
            if status != "CORR":
                print(
                    f"{meas} ({level}): {eng_V(result)}, status: {status}, reason: {reason}"
                )
            else:
                print(f"{meas} ({level}): {eng_V(result)}")
        else:
            if status != "CORR":
                print(f"{meas}: {eng_V(result)}, status: {status}, reason: {reason}")
            else:
                print(f"{meas}: {eng_V(result)}")

    # Check error queue.
    check_error_queue("End of program")

    # Exit program.
    exit_program()