Beispiel #1
0
def me0_elink_scan(system, oh_select, vfat_list):
    print("ME0 Elink Scan")

    n_err_vfat_elink = {}
    for vfat in vfat_list:  # Loop over all vfats
        n_err_vfat_elink[vfat] = {}
        for elink in range(0, 28):  # Loop for all 28 RX elinks
            print("VFAT%02d , ELINK %02d" % (vfat, elink))
            # Disable RX elink under test
            setVfatRxEnable(system, oh_select, vfat, 0, elink)

            # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
            sleep(0.1)
            gem_utils.gem_link_reset()
            sleep(0.001)

            gbt, gbt_select, elink_old, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
                vfat)
            oh_ver = get_oh_ver(oh_select, gbt_select)
            gem_utils.check_gbt_link_ready(oh_select, gbt_select)

            hwid_node = gem_utils.get_backend_node(
                "BEFE.GEM.OH.OH%d.GEB.VFAT%d.HW_ID" % (oh_select, vfat))
            n_err = 0
            for iread in range(10):
                hwid = gem_utils.simple_read_backend_reg(hwid_node, -9999)
                if hwid == -9999:
                    n_err += 1
            n_err_vfat_elink[vfat][elink] = n_err

            setVfatRxEnable(system, oh_select, vfat, 1, elink)
        print("")

    sleep(0.1)
    gem_utils.gem_link_reset()

    print("Elink mapping results: \n")
    for vfat in vfat_list:
        for elink in range(0, 28):
            sys.stdout.write("VFAT%02d , ELINK %02d:" % (vfat, elink))
            if n_err_vfat_elink[vfat][elink] == 10:
                char = Colors.GREEN + "+\n" + Colors.ENDC
            else:
                char = Colors.RED + "-\n" + Colors.ENDC
            sys.stdout.write("%s" % char)
            sys.stdout.flush()
        print("")
Beispiel #2
0
def gbt_phase_scan(gem, system, oh_select, daq_err, vfat_list, depth,
                   bestphase_list):
    print("ME0 Phase Scan depth=%s transactions" % (str(depth)))

    if bestphase_list != {}:
        print("Setting phases for VFATs only, not scanning")
        for vfat in vfat_list:
            set_bestphase = bestphase_list[vfat]
            setVfatRxPhase(system, oh_select, vfat, set_bestphase)
            print("Phase set for VFAT#%02d to: %s" %
                  (vfat, hex(set_bestphase)))
        return

    resultDir = "results"
    try:
        os.makedirs(resultDir)  # create directory for results
    except FileExistsError:  # skip if directory already exists
        pass
    vfatDir = "results/vfat_data"
    try:
        os.makedirs(vfatDir)  # create directory for VFAT data
    except FileExistsError:  # skip if directory already exists
        pass
    dataDir = "results/vfat_data/vfat_phase_scan_results"
    try:
        os.makedirs(dataDir)  # create directory for data
    except FileExistsError:  # skip if directory already exists
        pass
    now = str(datetime.datetime.now())[:16]
    now = now.replace(":", "_")
    now = now.replace(" ", "_")
    filename = dataDir + "/%s_OH%d_vfat_phase_scan_results_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w")
    filename_data = dataDir + "/%s_OH%d_vfat_phase_scan_data_" % (
        gem, oh_select) + now + ".txt"
    file_out_data = open(filename_data, "w")
    file_out.write("vfat  phase\n")

    link_good = [[0 for phase in range(16)] for vfat in range(24)]
    sync_err_cnt = [[0 for phase in range(16)] for vfat in range(24)]
    cfg_run = [[0 for phase in range(16)] for vfat in range(24)]
    daq_crc_error = [[0 for phase in range(16)] for vfat in range(24)]
    errs = [[0 for phase in range(16)] for vfat in range(24)]

    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
        0)

    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
            vfat)
        oh_ver = get_oh_ver(oh_select, gbt_select)
        gem_utils.check_gbt_link_ready(oh_select, gbt_select)

        #print("Configuring VFAT %d" % (vfat))
        #hwid_node = gem_utils.get_backend_node("BEFE.GEM.OH.OH%d.GEB.VFAT%d.HW_ID" % (oh_select, vfat))
        #output = gem_utils.simple_read_backend_reg(hwid_node, -9999)
        #if output == -9999:
        #    setVfatRxPhase(system, oh_select, vfat, 6)
        #    output = simple_read_backend_reg(hwid_node, -9999)
        #    if output == -9999:
        #        setVfatRxPhase(system, oh_select, vfat, 12)
        #        output = gem_utils.simple_read_backend_reg(hwid_node, -9999)
        #        if output == -9999:
        #            setVfatRxPhase(system, oh_select, vfat, 0)
        #            print (Colors.RED + "Cannot configure VFAT %d"%(vfat) + Colors.ENDC)
        #            terminate()
        #configureVfat(1, vfat, oh_select, 0)
        #for i in range(128):
        #    enableVfatchannel(vfat, oh_select, i, 0, 0) # unmask all channels and disable calpulsing
        #gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_RUN"%(oh_select,vfat)), 0)

    # Configure TTC Generator
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"),
        500)  # 80 kHz
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node(
            "BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"),
        0)  # Disable Calpulse
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"),
        10000)
    cyclic_running_node = gem_utils.get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")

    for phase in range(0, 16):
        print("Scanning phase %d" % phase)

        # set phases for all vfats under test
        for vfat in vfat_list:
            setVfatRxPhase(system, oh_select, vfat, phase)

        # read cfg_run some number of times, check link good status and sync errors
        print("Checking errors: ")
        for vfat in vfat_list:
            gbt, gbt_select, elink, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
                vfat)
            oh_ver = get_oh_ver(oh_select, gbt_select)
            # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
            sleep(0.1)
            gem_utils.gem_link_reset()
            sleep(0.1)

            # Check Slow Control
            cfg_node = gem_utils.get_backend_node(
                "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_RUN" % (oh_select, vfat))
            for iread in range(depth):
                vfat_cfg_run = gem_utils.simple_read_backend_reg(
                    cfg_node, 9999)
                if vfat_cfg_run != 0 and vfat_cfg_run != 1:
                    cfg_run[vfat][phase] = 1
                    break
                #cfg_run[vfat][phase] += (vfat_cfg_run != 0 and vfat_cfg_run != 1)

            # Check Link Good and Sync Errors
            link_node = gem_utils.get_backend_node(
                "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" % (oh_select, vfat))
            sync_node = gem_utils.get_backend_node(
                "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.SYNC_ERR_CNT" %
                (oh_select, vfat))
            link_good[vfat][phase] = gem_utils.simple_read_backend_reg(
                link_node, 0)
            sync_err_cnt[vfat][phase] = gem_utils.simple_read_backend_reg(
                sync_node, 9999)

            daq_crc_error[vfat][phase] = -1
            # Check DAQ event counter and CRC errors with L1A if link and slow control good
            if daq_err:
                if system == "dryrun" or (link_good[vfat][phase] == 1
                                          and sync_err_cnt[vfat][phase] == 0
                                          and cfg_run[vfat][phase] == 0):
                    configureVfat(1, vfat, oh_select,
                                  1)  # configure VFAT with low threshold
                    #write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_THR_ARM_DAC"%(oh_select,vfat)), 0) # low threshold for random data
                    #write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_RUN"%(oh_select,vfat)), 1)
                    for i in range(128):
                        enableVfatchannel(
                            vfat, oh_select, i, 0,
                            0)  # unmask all channels and disable calpulsing

                    # Send L1A to get DAQ events from VFATs
                    gem_utils.write_backend_reg(
                        gem_utils.get_backend_node(
                            "BEFE.GEM.TTC.GENERATOR.CYCLIC_START"), 1)
                    cyclic_running = 1
                    while cyclic_running:
                        cyclic_running = gem_utils.read_backend_reg(
                            cyclic_running_node)

                    daq_event_counter = gem_utils.read_backend_reg(
                        gem_utils.get_backend_node(
                            "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.DAQ_EVENT_CNT" %
                            (oh_select, vfat)))
                    if system == "dryrun":
                        daq_crc_error[vfat][phase] = gem_utils.read_backend_reg(
                            gem_utils.get_backend_node(
                                "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.DAQ_CRC_ERROR_CNT"
                                % (oh_select, vfat)))
                    else:
                        if daq_event_counter == 10000 % (2**16):
                            daq_crc_error[vfat][
                                phase] = gem_utils.read_backend_reg(
                                    gem_utils.get_backend_node(
                                        "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.DAQ_CRC_ERROR_CNT"
                                        % (oh_select, vfat)))
                        else:
                            print(Colors.YELLOW +
                                  "\tProblem with DAQ event counter=%d" %
                                  (daq_event_counter) + Colors.ENDC)
                    configureVfat(0, vfat, oh_select, 0)  # unconfigure VFAT
                    #write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_RUN"%(oh_select,vfat)), 0)
            else:
                daq_crc_error[vfat][phase] = 0

            result_str = ""
            if link_good[vfat][phase] == 1 and sync_err_cnt[vfat][
                    phase] == 0 and cfg_run[vfat][
                        phase] == 0 and daq_crc_error[vfat][phase] == 0:
                result_str += Colors.GREEN
            else:
                result_str += Colors.RED
            if daq_err:
                result_str += "\tResults of VFAT#%02d: link_good=%d, sync_err_cnt=%d, slow_control_bad=%d, daq_crc_errors=%d" % (
                    vfat, link_good[vfat][phase], sync_err_cnt[vfat][phase],
                    cfg_run[vfat][phase], daq_crc_error[vfat][phase])
            else:
                result_str += "\tResults of VFAT#%02d: link_good=%d, sync_err_cnt=%d, slow_control_bad=%d" % (
                    vfat, link_good[vfat][phase], sync_err_cnt[vfat][phase],
                    cfg_run[vfat][phase])
            result_str += Colors.ENDC
            print(result_str)
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)

    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
    centers = 24 * [0]
    widths = 24 * [0]

    for vfat in vfat_list:
        for phase in range(0, 16):
            errs[vfat][phase] = (not link_good[vfat][phase] == 1) + (
                not sync_err_cnt[vfat][phase]
                == 0) + (not cfg_run[vfat][phase]
                         == 0) + (not daq_crc_error[vfat][phase] == 0)
        centers[vfat], widths[vfat] = find_phase_center(errs[vfat])

    print("\nPhase Scan Results:")
    file_out_data.write("\nPhase Scan Results:\n")
    bestphase_vfat = 24 * [0]
    for vfat in vfat_list:
        phase_print = "VFAT%02d: " % (vfat)
        for phase in range(0, 16):

            if (widths[vfat] > 0 and phase == centers[vfat]):
                char = Colors.GREEN + "+" + Colors.ENDC
                bestphase_vfat[vfat] = phase
            elif (errs[vfat][phase]):
                char = Colors.RED + "-" + Colors.ENDC
            else:
                char = Colors.YELLOW + "x" + Colors.ENDC

            phase_print += "%s" % char
        if widths[vfat] < 3:
            phase_print += Colors.RED + " (center=%d, width=%d) BAD" % (
                centers[vfat], widths[vfat]) + Colors.ENDC
        elif widths[vfat] < 5:
            phase_print += Colors.YELLOW + " (center=%d, width=%d) WARNING" % (
                centers[vfat], widths[vfat]) + Colors.ENDC
        else:
            phase_print += Colors.GREEN + " (center=%d, width=%d) GOOD" % (
                centers[vfat], widths[vfat]) + Colors.ENDC
        print(phase_print)
        file_out_data.write(phase_print + "\n")

    # set phases for all vfats under test
    print("\nSetting all VFAT phases to best phases: ")
    for vfat in vfat_list:
        set_bestphase = bestphase_vfat[vfat]
        setVfatRxPhase(system, oh_select, vfat, set_bestphase)
        print("Phase set for VFAT#%02d to: %s" % (vfat, hex(set_bestphase)))
    for vfat in range(0, 24):
        file_out.write("%d  0x%x\n" % (vfat, bestphase_vfat[vfat]))

    sleep(0.1)
    gem_utils.gem_link_reset()
    print("")
    file_out.close()
    file_out_data.close()
def main(system, oh_select, gbt_list, relay_number, niter):

    if sys.version_info[0] < 3:
        raise Exception("Python version 3.x required")

    relay_object = ethernet_relay.ethernet_relay()
    connect_status = relay_object.connectToDevice()
    if not connect_status:
        print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
        rw_terminate()

    # Get first list of registers to compare
    print(
        "Turning on power and getting initial list of registers and turning off power"
    )
    set_status = relay_object.relay_set(relay_number, 1)
    if not set_status:
        print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
        rw_terminate()
    read_status = relay_object.relay_read(relay_number)
    if not read_status:
        print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
        rw_terminate()
    sleep(10)

    reg_list_boss = {}
    reg_list_sub = {}
    n_rw_reg = 0
    for gbt in gbt_list["boss"]:
        reg_list_boss[gbt] = {}
        oh_ver = get_oh_ver(str(oh_select), str(gbt))
        if oh_ver == 1:
            n_rw_reg = (0x13C + 1)
        if oh_ver == 2:
            n_rw_reg = (0x14F + 1)
        select_ic_link(oh_select, gbt)
        for reg in range(n_rw_reg):
            reg_list_boss[gbt][reg] = mpeek(reg)
    for gbt in gbt_list["sub"]:
        reg_list_sub[gbt] = {}
        oh_ver = get_oh_ver(str(oh_select), str(gbt))
        select_ic_link(oh_select, gbt)
        if oh_ver == 1:
            for i in range(0, 10):
                test_read = mpeek(0x00)
            n_rw_reg = (0x13C + 1)
        if oh_ver == 2:
            n_rw_reg = (0x14F + 1)
        for reg in range(n_rw_reg):
            reg_list_sub[gbt][reg] = mpeek(reg)

    set_status = relay_object.relay_set(relay_number, 0)
    if not set_status:
        print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
        rw_terminate()
    read_status = relay_object.relay_read(relay_number)
    if not read_status:
        print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
        rw_terminate()
    sleep(10)

    n_error_backend_ready_boss = {}
    n_error_backend_ready_sub = {}
    n_error_uplink_fec_boss = {}
    n_error_uplink_fec_sub = {}
    n_error_pusm_ready_boss = {}
    n_error_pusm_ready_sub = {}
    n_error_mode_boss = {}
    n_error_mode_sub = {}
    n_error_reg_list_boss = {}
    n_error_reg_list_sub = {}

    for gbt in gbt_list["boss"]:
        n_error_backend_ready_boss[gbt] = 0
        n_error_uplink_fec_boss[gbt] = 0
        n_error_pusm_ready_boss[gbt] = 0
        n_error_mode_boss[gbt] = 0
        n_error_reg_list_boss[gbt] = 0
    for gbt in gbt_list["sub"]:
        n_error_backend_ready_sub[gbt] = 0
        n_error_uplink_fec_sub[gbt] = 0
        n_error_pusm_ready_sub[gbt] = 0
        n_error_mode_sub[gbt] = 0
        n_error_reg_list_sub[gbt] = 0

    print("Begin powercycle iteration\n")
    # Power cycle interations
    for n in range(0, niter):
        print("Iteration: %d\n" % (n + 1))

        # Turn on relay
        set_status = relay_object.relay_set(relay_number, 1)
        if not set_status:
            print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
            rw_terminate()
        read_status = relay_object.relay_read(relay_number)
        if not read_status:
            print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
            rw_terminate()
        sleep(10)

        # Link reset
        gem_utils.gem_link_reset()
        sleep(2)

        # Check lpGBT status
        # Boss
        for gbt in gbt_list["boss"]:
            oh_ver = get_oh_ver(str(oh_select), str(gbt))
            select_ic_link(oh_select, gbt)
            n_rw_reg = 0
            print("Boss lpGBT %d: " % gbt)

            # Check Link Ready
            link_ready = gem_utils.read_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH_LINKS.OH%s.GBT%s_READY" % (oh_select, gbt)))
            if (link_ready != 1):
                print(Colors.YELLOW + "  Link NOT READY" + Colors.ENDC)
                n_error_backend_ready_boss[gbt] += 1
            else:
                print(Colors.GREEN + "  Link READY" + Colors.ENDC)

            # Check Uplink FEC Errors
            n_fec_errors = gem_utils.read_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH_LINKS.OH%d.GBT%d_FEC_ERR_CNT" %
                    (oh_select, gbt)))
            if n_fec_errors != 0:
                print(Colors.YELLOW + "  FEC Errors: %d" % (n_fec_errors) +
                      Colors.ENDC)
                n_error_uplink_fec_boss[gbt] += 1
            else:
                print(Colors.GREEN + "  No FEC Errors" + Colors.ENDC)

            # Check lpGBT PUSM READY and MODE
            if oh_ver == 1:
                ready_value = 18
                mode_value = 11
                mode = (mpeek(0x140) & 0xF0) >> 4
                pusmstate = mpeek(0x1C7)
            elif oh_ver == 2:
                ready_value = 19
                mode_value = 11
                mode = (mpeek(0x150) & 0xF0) >> 4
                pusmstate = mpeek(0x1D9)

            if mode != mode_value:
                n_error_mode_boss[gbt] += 1
                print(Colors.YELLOW + "  Incorrect mode: %d" % mode +
                      Colors.ENDC)
            else:
                print(Colors.GREEN + "  Correct mode: %d" % mode + Colors.ENDC)
            if pusmstate != ready_value:
                n_error_pusm_ready_boss[gbt] += 1
                print(Colors.YELLOW +
                      "  Incorrect PUSM State: %d" % pusmstate + Colors.ENDC)
            else:
                print(Colors.GREEN + "  Correct PUSM State: %d" % pusmstate +
                      Colors.ENDC)

            # Check register list
            if oh_ver == 1:
                n_rw_reg = (0x13C + 1)
            if oh_ver == 2:
                n_rw_reg = (0x14F + 1)
            for reg in range(n_rw_reg):
                val = mpeek(reg)
                if val != reg_list_boss[gbt][reg]:
                    n_error_reg_list_boss[gbt] += 1
                    print(Colors.YELLOW +
                          "  Register 0x%02X value mismatch" % reg +
                          Colors.ENDC)

        # Sub
        for gbt in gbt_list["sub"]:
            oh_ver = get_oh_ver(str(oh_select), str(gbt))
            select_ic_link(oh_select, gbt)
            n_rw_reg = 0
            print("Sub lpGBT %d: " % gbt)

            # Check Link Ready
            link_ready = gem_utils.read_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH_LINKS.OH%s.GBT%s_READY" % (oh_select, gbt)))
            if (link_ready != 1):
                print(Colors.YELLOW + "  Link NOT READY" + Colors.ENDC)
                n_error_backend_ready_sub[gbt] += 1
            else:
                print(Colors.GREEN + "  Link READY" + Colors.ENDC)

            # Check Uplink FEC Errors
            n_fec_errors = gem_utils.read_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH_LINKS.OH%d.GBT%d_FEC_ERR_CNT" %
                    (oh_select, gbt)))
            if n_fec_errors != 0:
                print(Colors.YELLOW + "  FEC Errors: %d" % (n_fec_errors) +
                      Colors.ENDC)
                n_error_uplink_fec_sub[gbt] += 1
            else:
                print(Colors.GREEN + "  No FEC Errors" + Colors.ENDC)

            # Check lpGBT PUSM READY and MODE
            if oh_ver == 1:
                for i in range(0, 10):
                    test_read = mpeek(0x00)
                ready_value = 18
                mode_value = 9
                mode = (mpeek(0x140) & 0xF0) >> 4
                pusmstate = mpeek(0x1C7)
            elif oh_ver == 2:
                ready_value = 19
                mode_value = 9
                mode = (mpeek(0x150) & 0xF0) >> 4
                pusmstate = mpeek(0x1D9)

            if mode != mode_value:
                n_error_mode_sub[gbt] += 1
                print(Colors.YELLOW + "  Incorrect mode: %d" % mode +
                      Colors.ENDC)
            else:
                print(Colors.GREEN + "  Correct mode: %d" % mode + Colors.ENDC)
            if pusmstate != ready_value:
                n_error_pusm_ready_sub[gbt] += 1
                print(Colors.YELLOW +
                      "  Incorrect PUSM State: %d" % pusmstate + Colors.ENDC)
            else:
                print(Colors.GREEN + "  Correct PUSM State: %d" % pusmstate +
                      Colors.ENDC)

            # Check register list
            if oh_ver == 1:
                n_rw_reg = (0x13C + 1)
            if oh_ver == 2:
                n_rw_reg = (0x14F + 1)
            for reg in range(n_rw_reg):
                val = mpeek(reg)
                if val != reg_list_sub[gbt][reg]:
                    n_error_reg_list_sub[gbt] += 1
                    print(Colors.YELLOW +
                          "  Register 0x%02X value mismatch" % reg +
                          Colors.ENDC)

        print("")
        # Turn off relay
        set_status = relay_object.relay_set(relay_number, 0)
        if not set_status:
            print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
            rw_terminate()
        read_status = relay_object.relay_read(relay_number)
        if not read_status:
            print(Colors.RED + "ERROR: Exiting" + Colors.ENDC)
            rw_terminate()

        sleep(10)  # To allow power supply to ramp down

    print("\nEnd of powercycle iteration")
    print("Number of iterations: %d\n" % niter)

    # Results
    print("Result For lpGBTs: \n")
    for gbt in gbt_list["boss"]:
        print("Boss lpGBT %d: " % gbt)
        str_n_error_backend_ready_boss = ""
        str_n_error_uplink_fec_boss = ""
        str_n_error_mode_boss = ""
        str_n_error_pusm_ready_boss = ""
        str_n_error_reg_list_boss = ""
        if n_error_backend_ready_boss[gbt] == 0:
            str_n_error_backend_ready_boss += Colors.GREEN
        else:
            str_n_error_backend_ready_boss += Colors.YELLOW
        if n_error_uplink_fec_boss[gbt] == 0:
            str_n_error_uplink_fec_boss += Colors.GREEN
        else:
            str_n_error_uplink_fec_boss += Colors.YELLOW
        if n_error_mode_boss[gbt] == 0:
            str_n_error_mode_boss += Colors.GREEN
        else:
            str_n_error_mode_boss += Colors.YELLOW
        if n_error_pusm_ready_boss[gbt] == 0:
            str_n_error_pusm_ready_boss += Colors.GREEN
        else:
            str_n_error_pusm_ready_boss += Colors.YELLOW
        if n_error_reg_list_boss[gbt] == 0:
            str_n_error_reg_list_boss += Colors.GREEN
        else:
            str_n_error_reg_list_boss += Colors.YELLOW
        str_n_error_backend_ready_boss += "  Number of Backend READY Status Errors: %d" % (
            n_error_backend_ready_boss[gbt])
        str_n_error_uplink_fec_boss += "  Number of Powercycles with Uplink FEC Errors: %d" % n_error_uplink_fec_boss[
            gbt]
        str_n_error_mode_boss += "  Number of Mode Errors: %d" % n_error_mode_boss[
            gbt]
        str_n_error_pusm_ready_boss += "  Number of PUSMSTATE Errors: %d" % n_error_pusm_ready_boss[
            gbt]
        str_n_error_reg_list_boss += "  Number of Register Value Errors: %d" % n_error_reg_list_boss[
            gbt]
        str_n_error_backend_ready_boss += Colors.ENDC
        str_n_error_uplink_fec_boss += Colors.ENDC
        str_n_error_mode_boss += Colors.ENDC
        str_n_error_pusm_ready_boss += Colors.ENDC
        str_n_error_reg_list_boss += Colors.ENDC
        print(str_n_error_backend_ready_boss)
        print(str_n_error_uplink_fec_boss)
        print(str_n_error_mode_boss)
        print(str_n_error_pusm_ready_boss)
        print(str_n_error_reg_list_boss)

    print("")
    for gbt in gbt_list["sub"]:
        print("Sub lpGBT %d: " % gbt)
        str_n_error_backend_ready_sub = ""
        str_n_error_uplink_fec_sub = ""
        str_n_error_mode_sub = ""
        str_n_error_pusm_ready_sub = ""
        str_n_error_reg_list_sub = ""
        if n_error_backend_ready_sub[gbt] == 0:
            str_n_error_backend_ready_sub += Colors.GREEN
        else:
            str_n_error_backend_ready_sub += Colors.YELLOW
        if n_error_uplink_fec_sub[gbt] == 0:
            str_n_error_uplink_fec_sub += Colors.GREEN
        else:
            str_n_error_uplink_fec_sub += Colors.YELLOW
        if n_error_mode_sub[gbt] == 0:
            str_n_error_mode_sub += Colors.GREEN
        else:
            str_n_error_mode_sub += Colors.YELLOW
        if n_error_pusm_ready_sub[gbt] == 0:
            str_n_error_pusm_ready_sub += Colors.GREEN
        else:
            str_n_error_pusm_ready_sub += Colors.YELLOW
        if n_error_reg_list_sub[gbt] == 0:
            str_n_error_reg_list_sub += Colors.GREEN
        else:
            str_n_error_reg_list_sub += Colors.YELLOW
        str_n_error_backend_ready_sub += "  Number of Backend READY Status Errors: %d" % (
            n_error_backend_ready_sub[gbt])
        str_n_error_uplink_fec_sub += "  Number of Powercycles with Uplink FEC Errors: %d" % n_error_uplink_fec_sub[
            gbt]
        str_n_error_mode_sub += "  Number of Mode Errors: %d" % n_error_mode_sub[
            gbt]
        str_n_error_pusm_ready_sub += "  Number of PUSMSTATE Errors: %d" % n_error_pusm_ready_sub[
            gbt]
        str_n_error_reg_list_sub += "  Number of Register Value Errors: %d" % n_error_reg_list_sub[
            gbt]
        str_n_error_backend_ready_sub += Colors.ENDC
        str_n_error_uplink_fec_sub += Colors.ENDC
        str_n_error_mode_sub += Colors.ENDC
        str_n_error_pusm_ready_sub += Colors.ENDC
        str_n_error_reg_list_sub += Colors.ENDC
        print(str_n_error_backend_ready_sub)
        print(str_n_error_uplink_fec_sub)
        print(str_n_error_mode_sub)
        print(str_n_error_pusm_ready_sub)
        print(str_n_error_reg_list_sub)

    print("")
Beispiel #4
0
def vfat_sbit(gem, system, oh_select, vfat_list, nl1a, calpulse_only,
              align_phases, l1a_bxgap, set_cal_mode, cal_dac, min_error_limit,
              bestphase_list):
    print("%s VFAT S-Bit Phase Scan\n" % gem)

    if bestphase_list != {}:
        print("Setting phases for VFATs only, not scanning")
        for vfat in vfat_list:
            sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
            for elink in range(0, 8):
                set_bestphase = bestphase_list[vfat][elink]
                setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink],
                                 set_bestphase)
                print("VFAT %02d: Phase set for ELINK %02d to: %s" %
                      (vfat, elink, hex(set_bestphase)))
        return

    resultDir = "results"
    try:
        os.makedirs(resultDir)  # create directory for results
    except FileExistsError:  # skip if directory already exists
        pass
    vfatDir = "results/vfat_data"
    try:
        os.makedirs(vfatDir)  # create directory for VFAT data
    except FileExistsError:  # skip if directory already exists
        pass
    dataDir = "results/vfat_data/vfat_sbit_phase_scan_results"
    try:
        os.makedirs(dataDir)  # create directory for data
    except FileExistsError:  # skip if directory already exists
        pass
    now = str(datetime.datetime.now())[:16]
    now = now.replace(":", "_")
    now = now.replace(" ", "_")
    filename = dataDir + "/%s_OH%d_vfat_sbit_phase_scan_results_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w")
    filename_data = dataDir + "/%s_OH%d_vfat_sbit_phase_scan_data_" % (
        gem, oh_select) + now + ".txt"
    file_out_data = open(filename_data, "w")
    file_out.write("vfat  elink  phase\n")

    errs = [[[0 for phase in range(16)] for elink in range(0, 8)]
            for vfat in range(24)]

    gem_utils.global_reset()
    sleep(0.1)
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
        1)

    # Reading S-bit counters
    cyclic_running_node = gem_utils.get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    l1a_node = gem_utils.get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")
    calpulse_node = gem_utils.get_backend_node(
        "BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")

    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"),
        oh_select)
    reset_sbit_monitor_node = gem_utils.get_backend_node(
        "BEFE.GEM.TRIGGER.SBIT_MONITOR.RESET")  # To reset S-bit Monitor
    reset_sbit_cluster_node = get_backend_node(
        "BEFE.GEM.TRIGGER.CTRL.CNT_RESET")  # To reset Cluster Counter
    sbit_monitor_nodes = []
    cluster_count_nodes = []
    for i in range(0, 8):
        sbit_monitor_nodes.append(
            gem_utils.get_backend_node(
                "BEFE.GEM.TRIGGER.SBIT_MONITOR.CLUSTER%d" % i))
        cluster_count_nodes.append(
            gem_utils.get_backend_node(
                "BEFE.GEM.TRIGGER.OH%d.CLUSTER_COUNT_%d_CNT" % (oh_select, i)))

    # Configure TTC generator
    ttc_cnt_reset_node = gem_utils.get_backend_node(
        "BEFE.GEM.TTC.CTRL.MODULE_RESET")
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    if calpulse_only:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 1)
    else:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"),
        l1a_bxgap)
    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"),
        nl1a)
    if l1a_bxgap >= 40:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 25)
    else:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 2)

    # Configure all VFATs
    for vfat in vfat_list:
        gbt, gbt_select, elink_daq, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
            vfat)
        oh_ver = get_oh_ver(oh_select, gbt_select)
        gem_utils.check_gbt_link_ready(oh_select, gbt_select)

        link_good = gem_utils.read_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" % (oh_select, vfat)))
        sync_err = gem_utils.read_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.OH_LINKS.OH%d.VFAT%d.SYNC_ERR_CNT" %
                (oh_select, vfat)))
        if system != "dryrun" and (link_good == 0 or sync_err > 0):
            print(Colors.RED + "Link is bad for VFAT# %02d" % (vfat) +
                  Colors.ENDC)
            gem_utils.terminate()

        # Configure the pulsing VFAT
        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                    (oh_select, vfat)), 1)
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                    (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                    (oh_select, vfat)), 2)
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                    (oh_select, vfat)), 0)
        else:
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                    (oh_select, vfat)), 0)
            gem_utils.write_backend_reg(
                gem_utils.get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                    (oh_select, vfat)), 0)
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DAC" % (oh_select, vfat)),
            cal_dac)
        for i in range(128):
            enableVfatchannel(vfat, oh_select, i, 1,
                              0)  # mask all channels and disable calpulsing

        # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
        sleep(0.1)
        gem_utils.gem_link_reset()
        sleep(0.1)

    s_bit_cluster_mapping = {}
    print("")

    # Starting Phase loop
    for phase in range(0, 16):
        print("Scanning phase %d" % phase)
        # set phases for all elinks in all vfats
        for vfat in vfat_list:
            sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
            for elink in range(0, 8):
                setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink],
                                 phase)

        # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
        sleep(0.1)
        gem_utils.gem_link_reset()
        sleep(0.1)

        print("Checking errors: ")
        # Starting VFAT loop
        for vfat in vfat_list:
            s_bit_cluster_mapping[vfat] = {}

            # Looping over all channels
            for channel in range(0, 128):
                s_bit_cluster_mapping[vfat][channel] = {}
                s_bit_cluster_mapping[vfat][channel]["calpulse_counter"] = 0
                s_bit_cluster_mapping[vfat][channel]["cluster_count"] = []
                s_bit_cluster_mapping[vfat][channel][
                    "sbit_monitor_cluster_size"] = []
                s_bit_cluster_mapping[vfat][channel][
                    "sbit_monitor_cluster_address"] = []

                # Enabling the pulsing channel
                enableVfatchannel(
                    vfat, oh_select, channel, 0,
                    1)  # unmask this channel and enable calpulsing

                # Reset L1A, CalPulse and S-bit monitor
                gem_utils.write_backend_reg(ttc_cnt_reset_node, 1)
                gem_utils.write_backend_reg(reset_sbit_monitor_node, 1)
                gem_utils.write_backend_reg(reset_sbit_cluster_node, 1)

                # Start the cyclic generator
                gem_utils.write_backend_reg(
                    gem_utils.get_backend_node(
                        "BEFE.GEM.TTC.GENERATOR.CYCLIC_START"), 1)
                cyclic_running = gem_utils.read_backend_reg(
                    cyclic_running_node)
                while cyclic_running:
                    cyclic_running = gem_utils.read_backend_reg(
                        cyclic_running_node)

                # Stop the cyclic generator
                gem_utils.write_backend_reg(
                    gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"),
                    1)

                l1a_counter = gem_utils.read_backend_reg(l1a_node)
                calpulse_counter = gem_utils.read_backend_reg(calpulse_node)

                for i in range(0, 8):
                    s_bit_cluster_mapping[vfat][channel][
                        "calpulse_counter"] = calpulse_counter
                    s_bit_cluster_mapping[vfat][channel][
                        "cluster_count"].append(
                            gem_utils.read_backend_reg(cluster_count_nodes[i]))
                    sbit_monitor_value = gem_utils.read_backend_reg(
                        sbit_monitor_nodes[i])
                    sbit_cluster_address = sbit_monitor_value & 0x7ff
                    sbit_cluster_size = ((sbit_monitor_value >> 11) & 0x7) + 1
                    s_bit_cluster_mapping[vfat][channel][
                        "sbit_monitor_cluster_size"].append(sbit_cluster_size)
                    s_bit_cluster_mapping[vfat][channel][
                        "sbit_monitor_cluster_address"].append(
                            sbit_cluster_address)

                # Disabling the pulsing channels
                enableVfatchannel(
                    vfat, oh_select, channel, 1,
                    0)  # mask this channel and disable calpulsing

            # Detecting bad phase for each Elink
            for elink in range(0, 8):
                for channel in range(elink * 16, elink * 16 + 16):
                    multiple_cluster_counts = 0
                    for i in range(1, 8):
                        if i == 1:
                            if s_bit_cluster_mapping[vfat][channel][
                                    "cluster_count"][
                                        i] != s_bit_cluster_mapping[vfat][
                                            channel]["calpulse_counter"]:
                                multiple_cluster_counts = 1
                        else:
                            if s_bit_cluster_mapping[vfat][channel][
                                    "cluster_count"][i] != 0:
                                multiple_cluster_counts = 1
                    n_clusters = 0
                    for i in range(0, 8):
                        if (s_bit_cluster_mapping[vfat][channel]
                            ["sbit_monitor_cluster_address"][i] == 0x7ff
                                and s_bit_cluster_mapping[vfat][channel]
                            ["sbit_monitor_cluster_size"][i] == 0x7):
                            continue
                        n_clusters += 1
                    if n_clusters > 1 or multiple_cluster_counts == 1:
                        errs[vfat][elink][phase] += 1

                if errs[vfat][elink][phase] == 0:
                    print(
                        Colors.GREEN +
                        "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"
                        % (phase, vfat, elink, errs[vfat][elink][phase]) +
                        Colors.ENDC)
                elif errs[vfat][elink][phase] < 16:
                    print(
                        Colors.YELLOW +
                        "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"
                        % (phase, vfat, elink, errs[vfat][elink][phase]) +
                        Colors.ENDC)
                else:
                    print(
                        Colors.RED +
                        "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"
                        % (phase, vfat, elink, errs[vfat][elink][phase]) +
                        Colors.ENDC)

            # End of Elink loop
            print("")
        print("")
        # End of VFAT loop
    # End of Phase loop
    if calpulse_only:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node(
                "BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        gem_utils.write_backend_reg(
            gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    # Unconfigure all VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        configureVfat(0, vfat, oh_select, 0)
        sleep(0.1)

    aligned_phases_center = [[-9999 for elink in range(8)]
                             for vfat in range(24)]
    for vfat in vfat_list:
        find_aligned_phase_center(vfat, errs[vfat], aligned_phases_center,
                                  min_error_limit)

    bestphase_vfat_elink = [[0 for elink in range(8)] for vfat in range(24)]
    print("\nPhase Scan Results:")
    file_out_data.write("\nPhase Scan Results:\n")
    for vfat in vfat_list:
        centers = 8 * [0]
        widths = 8 * [0]
        for elink in range(0, 8):
            centers[elink], widths[elink] = find_phase_center(
                errs[vfat][elink], min_error_limit)
            if not align_phases:
                if centers[elink] == 7 and (widths[elink] == 15
                                            or widths[elink] == 14):
                    if elink != 0:
                        centers[elink] = centers[elink - 1]
            else:
                new_center = aligned_phases_center[vfat][elink]
                if new_center != -9999:
                    if centers[elink] > new_center:
                        if new_center != 14:
                            bad_phase = -9999
                            for p in range(new_center, centers[elink] + 1):
                                if errs[vfat][elink][p] != 0:
                                    bad_phase = p
                                    break
                            if bad_phase == -9999:
                                centers[elink] = new_center + 1
                            else:
                                centers[elink] = new_center
                        else:
                            centers[elink] = new_center
                    elif centers[elink] < new_center:
                        if new_center != 0:
                            bad_phase = -9999
                            for p in range(centers[elink], new_center + 1):
                                if errs[vfat][elink][p] != 0:
                                    bad_phase = p
                                    break
                            if bad_phase == -9999:
                                centers[elink] = new_center - 1
                            else:
                                centers[elink] = new_center
                        else:
                            centers[elink] = new_center
                    else:
                        centers[elink] = new_center

        print("\nVFAT %02d :" % (vfat))
        file_out_data.write("\nVFAT %02d :\n" % (vfat))
        for elink in range(0, 8):
            phase_print = "  ELINK %02d: " % (elink)
            min_errors = min(errs[vfat][elink])
            if min_errors > min_error_limit:
                min_errors = 0
            for phase in range(0, 16):
                if (widths[elink] > 0 and phase == centers[elink]):
                    char = Colors.GREEN + "+" + Colors.ENDC
                    bestphase_vfat_elink[vfat][elink] = phase
                elif (errs[vfat][elink][phase] > min_errors):
                    char = Colors.RED + "-" + Colors.ENDC
                else:
                    char = Colors.YELLOW + "x" + Colors.ENDC

                phase_print += "%s" % char
            if widths[elink] < 3:
                phase_print += Colors.RED + " (center=%d, width=%d) BAD" % (
                    centers[elink], widths[elink]) + Colors.ENDC
            elif widths[elink] < 5:
                phase_print += Colors.YELLOW + " (center=%d, width=%d) WARNING" % (
                    centers[elink], widths[elink]) + Colors.ENDC
            else:
                phase_print += Colors.GREEN + " (center=%d, width=%d) GOOD" % (
                    centers[elink], widths[elink]) + Colors.ENDC
            print(phase_print)
            file_out_data.write(phase_print + "\n")

        # set phases for all elinks for this vfat
        print("\nVFAT %02d: Setting all ELINK phases to best phases: " %
              (vfat))
        sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
        for elink in range(0, 8):
            set_bestphase = bestphase_vfat_elink[vfat][elink]
            setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink],
                             set_bestphase)
            print("VFAT %02d: Phase set for ELINK %02d to: %s" %
                  (vfat, elink, hex(set_bestphase)))
    for vfat in range(0, 24):
        for elink in range(0, 8):
            file_out.write("%d  %d  0x%x\n" %
                           (vfat, elink, bestphase_vfat_elink[vfat][elink]))

    sleep(0.1)
    gem_utils.gem_link_reset()
    print("")
    file_out.close()
    file_out_data.close()

    gem_utils.write_backend_reg(
        gem_utils.get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
        0)
    print("\nS-bit phase scan done\n")
def sbit_phase_scan(ohN,
                    vfatNMin=0,
                    vfatNMax=11,
                    verbose=False,
                    print_result=True):

    VFAT_SBITS_out = []

    addrSbitMonReset = get_node(
        'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_MONITOR.RESET' % ohN)
    write_reg(get_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"), ohN)

    ##################
    # hard reset
    ##################

    for vfatN in range(vfatNMin, vfatNMax + 1):

        if print_result:
            print("")
            print(
                "####################################################################################################"
            )
            print("Scanning VFAT %i" % vfatN)
            print(
                "####################################################################################################"
            )
            print("")

        write_reg(get_node('BEFE.GEM.SLOW_CONTROL.SCA.CTRL.MODULE_RESET'), 0x1)
        gem.gem_hard_reset()
        sleep(0.3)
        gem.gem_link_reset()
        sleep(0.1)

        ##################
        #
        ##################

        addrCluster = [0] * 8
        for i in range(8):
            addrCluster[i] = get_node(
                'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_MONITOR.CLUSTER%i' % (ohN, i))

        configureVfatForPulsing(vfatN, ohN)

        err_matrix = [[0 for i in range(0, 2 * SCAN_RANGE + 1)]
                      for j in range(8)]

        write_reg(
            get_node("BEFE.GEM.OH.OH%i.FPGA.TRIG.CTRL.ALIGNED_COUNT_TO_READY" %
                     ohN), 0xfff)

        sot_reg = get_node(
            'BEFE.GEM.OH.OH%d.FPGA.TRIG.TIMING.SOT_TAP_DELAY_VFAT%s' %
            (ohN, vfatN))
        sot_dly_original = read_reg(sot_reg)

        for sot_dly in range(2):

            dly_offset = 0
            if (sot_dly == 0):
                dly_offset = SCAN_RANGE
            else:
                dly_offset = 0

            write_reg(sot_reg, dly_offset)
            sleep(0.0001)  # otherwise too fast on CVP13 :)
            sot_rdy = read_reg(
                get_node("BEFE.GEM.OH.OH%i.FPGA.TRIG.CTRL.SBIT_SOT_READY" %
                         ohN))
            sleep(0.1)
            if (not (sot_rdy >> vfatN) & 0x1):
                print("Sot not ready... cannot scan")
                sys.exit()

            for ibit in range(8):

                #   Set the SoT delay to 0 (min)
                tap_dly_reg = get_node(
                    'BEFE.GEM.OH.OH%d.FPGA.TRIG.TIMING.TAP_DELAY_VFAT%i_BIT%i'
                    % (ohN, vfatN, ibit))
                tap_dly_original = read_reg(tap_dly_reg)

                #                sbit_monitor_cluster_reg = get_node('BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_MONITOR.CLUSTER0' % (ohN))
                #                sbit_monitor_reset_reg   = get_node('BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_MONITOR.RESET' % (ohN))

                sbit_hitmap_msb_reg = get_node(
                    'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_HITMAP.VFAT%d_MSB' %
                    (ohN, vfatN))
                sbit_hitmap_lsb_reg = get_node(
                    'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_HITMAP.VFAT%d_LSB' %
                    (ohN, vfatN))
                sbit_hitmap_reset_reg = get_node(
                    'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_HITMAP.RESET' % (ohN))
                sbit_hitmap_ack_reg = get_node(
                    'BEFE.GEM.OH.OH%d.FPGA.TRIG.SBIT_HITMAP.ACQUIRE' % (ohN))

                write_reg(
                    get_node(
                        "BEFE.GEM.OH.OH%i.FPGA.TRIG.CTRL.TU_MASK.VFAT%i_TU_MASK"
                        % (ohN, vfatN)), 0xff ^ (1 << (ibit)))

                for delay in range(SCAN_RANGE + 1):

                    write_reg(tap_dly_reg, delay)

                    for islice in range(8):

                        trigger_channel = ibit * 8 + islice

                        for strip_odd in range(1):

                            strip = trigger_channel * 2 + strip_odd

                            write_reg(
                                get_node(
                                    "BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
                                1)
                            write_reg(
                                get_node(
                                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.VFAT_CHANNELS.CHANNEL%i"
                                    % (ohN, vfatN, strip)),
                                0x8000)  # enable calpulse and unmask
                            write_reg(
                                get_node(
                                    "BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
                                0)

                            for ipulse in range(1):

                                sleep(0.0001)

                                write_reg(sbit_hitmap_reset_reg, 1)
                                write_reg(sbit_hitmap_ack_reg, 1)

                                sleep(0.0001)

                                write_reg(sbit_hitmap_ack_reg, 0)

                                hit_map = (read_reg(sbit_hitmap_msb_reg) <<
                                           32) + read_reg(sbit_hitmap_lsb_reg)
                                hit_map_expected = 1 << trigger_channel

                                err = hit_map_expected != hit_map
                                if (err):
                                    err_matrix[ibit][delay - dly_offset +
                                                     SCAN_RANGE] += 1

                                if (hit_map != 0):
                                    if (err):
                                        if (verbose): print("FAIL:"),
                                    else:
                                        if (verbose): print("PASS:"******"ibit=%d, delay=%3i, slice=%i, ch_expect = %2d, hitmap=%s"
                                            %
                                            (ibit, delay - dly_offset, islice,
                                             trigger_channel, hex(hit_map)))
                                else:
                                    if (verbose):
                                        print("FAIL: no cluster found")

                            write_reg(
                                get_node(
                                    "BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
                                1)
                            write_reg(
                                get_node(
                                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.VFAT_CHANNELS.CHANNEL%i"
                                    % (ohN, vfatN, strip)),
                                0x4000)  # disable calpulse and mask
                            write_reg(
                                get_node(
                                    "BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"),
                                0)

            write_reg(tap_dly_reg, tap_dly_original)

        ngood_center = [0 for i in range(8)]
        ngood_width = [0 for i in range(8)]
        best_tap_delay = [0 for i in range(8)]

        min_center = 1000

        line = "      "
        for dly in range(2 * SCAN_RANGE + 1):
            text = "%2X" % (abs(dly - SCAN_RANGE) % 16)
            line = line + text

        print(line)

        for ibit in range(8):

            ngood = 0
            ngood_max = 0
            ngood_edge = 0

            for dly in range(2 * SCAN_RANGE + 1):
                if (err_matrix[ibit][dly] == 0):
                    ngood += 1
                    if (dly == 2 * SCAN_RANGE):
                        if (ngood > 0 and ngood >= ngood_max):
                            ngood_max = ngood
                            ngood_edge = dly
                            ngood = 0
                else:
                    if (ngood > 0 and ngood >= ngood_max):
                        ngood_max = ngood
                        ngood_edge = dly
                        ngood = 0
                    #print("%3i" % err_matrix[ibit][dly]),

            if (ngood_max > 0):
                ngood_width[ibit] = ngood_max

                # even windows
                if (ngood_max % 2 == 0):
                    ngood_center[ibit] = ngood_edge - (ngood_max / 2) - 1
                if (err_matrix[ibit][ngood_edge] >
                        err_matrix[ibit][ngood_edge - ngood_max - 1]):
                    ngood_center[ibit] = ngood_center[ibit]
                else:
                    ngood_center[ibit] = ngood_center[ibit] + 1

                # oddwindows
                if (ngood_max % 2 == 1):
                    ngood_center[ibit] = ngood_edge - (ngood_max / 2) - 1

                # minimum
                if (ngood_center[ibit] < min_center):
                    min_center = ngood_center[ibit]

        ################################################################################
        # Printout Timing Window
        ################################################################################

        for ibit in range(8):

            line = ("Sbit%i: " % ibit)

            for dly in range(2 * SCAN_RANGE + 1):
                if (err_matrix[ibit][dly] == 0):
                    if (dly == ngood_center[ibit]):
                        line = line + Colors.GREEN + "| "
                    else:
                        line = line + Colors.GREEN + "- "
                else:
                    line = line + Colors.RED + "x "

            line = line + Colors.ENDC
            if print_result:
                print(line)

        ################################################################################
        # Printout Summary
        ################################################################################

        if print_result:
            print("min center = %i" % min_center)

        best_sot_tap_delay = 99
        if (min_center - SCAN_RANGE < 0):
            best_sot_tap_delay = -1 * (min_center - SCAN_RANGE)
        else:
            best_sot_tap_delay = min_center

        if print_result:
            print("sot :           best_dly=% 2d" % (best_sot_tap_delay))
        ngood_center_offset = []
        for ibit in range(8):
            best_tap_delay[ibit] = ngood_center[ibit] - min_center
            if print_result:
                print("bit%i: center=% 2d best_dly=% 2d width=% 2d (%f ns)" %
                      (ibit, ngood_center[ibit] - SCAN_RANGE,
                       best_tap_delay[ibit], ngood_width[ibit],
                       ngood_width[ibit] * 78. / 1000))
            ngood_center_offset.append(ngood_center[ibit] - SCAN_RANGE)
        VFAT_SBITS_out.append(
            VFAT_SBIT(vfatN, ngood_center_offset, best_tap_delay, ngood_width))

    if print_result:
        print("")
        print("bye now..")

    return VFAT_SBITS_out
def vfat_sbit(gem, system, oh_select, vfat_list, nl1a, calpulse_only, align_phases, l1a_bxgap, set_cal_mode, cal_dac, min_error_limit, n_allowed_missing_hits, bestphase_list):
    print ("%s VFAT S-Bit Phase Scan\n"%gem)

    if bestphase_list!={}:
        print ("Setting phases for VFATs only, not scanning")
        for vfat in vfat_list:
            sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
            for elink in range(0,8):
                set_bestphase = bestphase_list[vfat][elink]
                setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink], set_bestphase)
                print ("VFAT %02d: Phase set for ELINK %02d to: %s" % (vfat, elink, hex(set_bestphase)))
        return

    resultDir = "results"
    try:
        os.makedirs(resultDir) # create directory for results
    except FileExistsError: # skip if directory already exists
        pass
    vfatDir = "results/vfat_data"
    try:
        os.makedirs(vfatDir) # create directory for VFAT data
    except FileExistsError: # skip if directory already exists
        pass
    dataDir = "results/vfat_data/vfat_sbit_phase_scan_results"
    try:
        os.makedirs(dataDir) # create directory for data
    except FileExistsError: # skip if directory already exists
        pass
    now = str(datetime.datetime.now())[:16]
    now = now.replace(":", "_")
    now = now.replace(" ", "_")
    filename = dataDir + "/%s_OH%d_vfat_sbit_phase_scan_results_"%(gem,oh_select) + now + ".txt"
    file_out = open(filename, "w")
    filename_data = dataDir + "/%s_OH%d_vfat_sbit_phase_scan_data_"%(gem,oh_select) + now + ".txt"
    file_out_data = open(filename_data, "w")
    file_out.write("vfat  elink  phase\n")

    errs = [[[0 for phase in range(16)] for elink in range(0,8)] for vfat in range(24)]

    gem_utils.global_reset()
    sleep(0.1)
    gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 1)

    # Reading S-bit counters
    cyclic_running_node = gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    l1a_node = gem_utils.get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")
    calpulse_node = gem_utils.get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")

    write_backend_reg(get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_OH_SBIT_ME0"), oh_select)
    elink_sbit_select_node = gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_ELINK_SBIT_ME0") # Node for selecting Elink to count
    channel_sbit_select_node = gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_SBIT_ME0") # Node for selecting S-bit to count
    elink_sbit_counter_node = gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SBIT0XE_COUNT_ME0") # S-bit counter for elink
    channel_sbit_counter_node = gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SBIT0XS_COUNT_ME0") # S-bit counter for specific channel
    reset_sbit_counter_node = gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.CTRL.SBIT_TEST_RESET")  # To reset all S-bit counters

    # Configure TTC generator
    ttc_cnt_reset_node = gem_utils.get_backend_node("BEFE.GEM.TTC.CTRL.MODULE_RESET")
    gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    if calpulse_only:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 1)
    else:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"), l1a_bxgap)
    gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"), nl1a)
    if l1a_bxgap >= 40:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 25)
    else:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 2)

    # Configure all VFATs
    for vfat in vfat_list:
        gbt, gbt_select, elink_daq, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(vfat)
        oh_ver = get_oh_ver(oh_select, gbt_select)
        gem_utils.check_gbt_link_ready(oh_select, gbt_select)

        link_good = gem_utils.read_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" % (oh_select, vfat)))
        sync_err = gem_utils.read_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.SYNC_ERR_CNT" % (oh_select, vfat)))
        if system!="dryrun" and (link_good == 0 or sync_err > 0):
            print (Colors.RED + "Link is bad for VFAT# %02d"%(vfat) + Colors.ENDC)
            gem_utils.terminate()

        # Configure the pulsing VFAT
        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 1)
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 2)
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)
        else:
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 0)
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DAC"% (oh_select, vfat)), cal_dac)
        for i in range(128):
            enableVfatchannel(vfat, oh_select, i, 1, 0) # mask all channels and disable calpulsing

        # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
        sleep(0.1)
        gem_utils.gem_link_reset()
        sleep(0.1)

    s_bit_channel_mapping = {}
    print ("")

    # Starting Phase loop
    for phase in range(0, 16):
        print ("Scanning phase %d"%phase)
        # set phases for all elinks in all vfats
        for vfat in vfat_list:
            sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
            for elink in range(0,8):
                setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink], phase)

        # Reset the link, give some time to accumulate any sync errors and then check VFAT comms
        sleep(0.1)
        gem_utils.gem_link_reset()
        sleep(0.1)

        print ("Checking errors: ")
        # Starting VFAT loop
        for vfat in vfat_list:
            gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_VFAT_SBIT_ME0"), vfat) # Select VFAT for reading S-bits
            s_bit_channel_mapping[vfat] = {}

            # Looping over all 8 elinks
            for elink in range(0,8):
                gem_utils.write_backend_reg(elink_sbit_select_node, elink) # Select elink for S-bit counter
                s_bit_channel_mapping[vfat][elink] = {}
                s_bit_matches = {}

                for sbit in range(elink*8,elink*8+8):
                    s_bit_matches[sbit] = 0

                # Looping over all channels in that elink
                for channel in range(elink*16,elink*16+16):
                    # Enabling the pulsing channel
                    enableVfatchannel(vfat, oh_select, channel, 0, 1) # unmask this channel and enable calpulsing

                    channel_sbit_counter_final = {}
                    sbit_channel_match = 0
                    s_bit_channel_mapping[vfat][elink][channel] = -9999

                    # Looping over all S-bits in that elink
                    for sbit in range(elink*8,elink*8+8):
                        # Reset L1A, CalPulse and S-bit counters
                        gem_utils.write_backend_reg(ttc_cnt_reset_node, 1)
                        gem_utils.write_backend_reg(reset_sbit_counter_node, 1)

                        gem_utils.write_backend_reg(channel_sbit_select_node, sbit) # Select S-bit for S-bit counter

                        # Start the cyclic generator
                        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_START"), 1)
                        cyclic_running = gem_utils.read_backend_reg(cyclic_running_node)
                        while cyclic_running:
                            cyclic_running = gem_utils.read_backend_reg(cyclic_running_node)

                        # Stop the cyclic generator
                        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)

                        elink_sbit_counter_final = gem_utils.read_backend_reg(elink_sbit_counter_node)
                        l1a_counter = gem_utils.read_backend_reg(l1a_node)
                        calpulse_counter = gem_utils.read_backend_reg(calpulse_node)

                        if abs(elink_sbit_counter_final - calpulse_counter) > n_allowed_missing_hits:
                            # Elink did not register the correct number of hits
                            s_bit_channel_mapping[vfat][elink][channel] = -9999
                            break
                        channel_sbit_counter_final[sbit] = gem_utils.read_backend_reg(channel_sbit_counter_node)

                        if calpulse_counter == 0:
                            # Calpulse Counter is 0
                            s_bit_channel_mapping[vfat][elink][channel] = -9999
                            break

                        if abs(channel_sbit_counter_final[sbit] - calpulse_counter) <= n_allowed_missing_hits:
                            if sbit_channel_match == 1:
                                # Multiple S-bits registered hits for calpulse on this channel
                                s_bit_channel_mapping[vfat][elink][channel] = -9999
                                break
                            if s_bit_matches[sbit] >= 2:
                                # S-bit already matched to 2 channels
                                s_bit_channel_mapping[vfat][elink][channel] = -9999
                                break
                            if s_bit_matches[sbit] == 1:
                                if channel%2==0:
                                    # S-bit already matched to an earlier odd numbered channel
                                    s_bit_channel_mapping[vfat][elink][channel] = -9999
                                    break
                                if s_bit_channel_mapping[vfat][elink][channel-1] != sbit:
                                    # S-bit matched to a different channel than the previous one
                                    s_bit_channel_mapping[vfat][elink][channel] = -9999
                                    break
                            s_bit_channel_mapping[vfat][elink][channel] = sbit
                            sbit_channel_match = 1
                            s_bit_matches[sbit] += 1
                    # End of S-bit loop for this channel

                    if s_bit_channel_mapping[vfat][elink][channel] == -9999:
                        errs[vfat][elink][phase] += 1

                    # Disabling the pulsing channels
                    enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask this channel and disable calpulsing
                # End of Channel loop

                if errs[vfat][elink][phase] == 0:
                    print (Colors.GREEN + "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"%(phase, vfat, elink, errs[vfat][elink][phase]) + Colors.ENDC)
                elif errs[vfat][elink][phase] < 16:
                    print (Colors.YELLOW + "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"%(phase, vfat, elink, errs[vfat][elink][phase]) + Colors.ENDC)
                else:
                    print (Colors.RED + "Phase: %d, VFAT %02d SBit ELINK %02d: nr. of channel errors=%d"%(phase, vfat, elink, errs[vfat][elink][phase]) + Colors.ENDC)

            # End of Elink loop
            print ("")
        print ("")
        # End of VFAT loop
    # End of Phase loop
    if calpulse_only:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    # Unconfigure all VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        configureVfat(0, vfat, oh_select, 0)
        sleep(0.1)

    aligned_phases_center = [[-9999 for elink in range(8)] for vfat in range(24)]
    for vfat in vfat_list:
         find_aligned_phase_center(vfat, errs[vfat], aligned_phases_center, min_error_limit)

    bestphase_vfat_elink = [[0 for elink in range(8)] for vfat in range(24)]
    print ("\nPhase Scan Results:")
    file_out_data.write("\nPhase Scan Results:\n")
    for vfat in vfat_list:
        centers = 8*[0]
        widths  = 8*[0]
        for elink in range(0,8):
            centers[elink], widths[elink] = find_phase_center(errs[vfat][elink], min_error_limit)
            if not align_phases:
                if centers[elink] == 7 and (widths[elink]==15 or widths[elink]==14):
                    if elink!=0:
                        centers[elink] = centers[elink-1]
            else:
                new_center = aligned_phases_center[vfat][elink]
                if new_center != -9999:
                    if centers[elink] > new_center:
                        if new_center != 14:
                            bad_phase = -9999
                            for p in range(new_center, centers[elink]+1):
                                if errs[vfat][elink][p] != 0:
                                    bad_phase = p
                                    break
                            if bad_phase == -9999:
                                centers[elink] = new_center + 1
                            else:
                                centers[elink] = new_center
                        else:
                            centers[elink] = new_center
                    elif centers[elink] < new_center:
                        if new_center != 0:
                            bad_phase = -9999
                            for p in range(centers[elink], new_center+1):
                                if errs[vfat][elink][p] != 0:
                                    bad_phase = p
                                    break
                            if bad_phase == -9999:
                                centers[elink] = new_center - 1
                            else:
                                centers[elink] = new_center
                        else:
                            centers[elink] = new_center
                    else:
                        centers[elink] = new_center

        print ("\nVFAT %02d :" %(vfat))
        file_out_data.write("\nVFAT %02d :\n" %(vfat))
        for elink in range(0,8):
            phase_print = "  ELINK %02d: " % (elink)
            min_errors = min(errs[vfat][elink])
            if min_errors > min_error_limit:
                min_errors = 0
            for phase in range(0, 16):
                if (widths[elink]>0 and phase==centers[elink]):
                    char=Colors.GREEN + "+" + Colors.ENDC
                    bestphase_vfat_elink[vfat][elink] = phase
                elif (errs[vfat][elink][phase] > min_errors):
                    char=Colors.RED + "-" + Colors.ENDC
                else:
                    char = Colors.YELLOW + "x" + Colors.ENDC

                phase_print += "%s" %char
            if widths[elink]<3:
                phase_print += Colors.RED + " (center=%d, width=%d) BAD" % (centers[elink], widths[elink]) + Colors.ENDC
            elif widths[elink]<5:
                phase_print += Colors.YELLOW + " (center=%d, width=%d) WARNING" % (centers[elink], widths[elink]) + Colors.ENDC
            else:
                phase_print += Colors.GREEN + " (center=%d, width=%d) GOOD" % (centers[elink], widths[elink]) + Colors.ENDC
            print(phase_print)
            file_out_data.write(phase_print + "\n")

        # set phases for all elinks for this vfat
        print ("\nVFAT %02d: Setting all ELINK phases to best phases: "%(vfat))
        sbit_elinks = gem_utils.me0_vfat_to_sbit_elink(vfat)
        for elink in range(0,8):
            set_bestphase = bestphase_vfat_elink[vfat][elink]
            setVfatSbitPhase(system, oh_select, vfat, sbit_elinks[elink], set_bestphase)
            print ("VFAT %02d: Phase set for ELINK %02d to: %s" % (vfat, elink, hex(set_bestphase)))
    for vfat in range(0,24):
        for elink in range(0,8):
            file_out.write("%d  %d  0x%x\n"%(vfat,elink,bestphase_vfat_elink[vfat][elink]))

    sleep(0.1)
    gem_utils.gem_link_reset()
    print ("")
    file_out.close()
    file_out_data.close()

    gem_utils.write_backend_reg(gem_utils.get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    print ("\nS-bit phase scan done\n")