Beispiel #1
0
def setVfatSbitPhase(system, oh_select, vfat, sbit_elink, phase):
    gbt, gbt_select, rx_elink, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
        vfat)
    oh_ver = get_oh_ver(oh_select, gbt_select)
    select_ic_link(oh_select, gbt_select)

    if gbt == "boss":
        if oh_ver == 1:
            config = config_boss_v1
        elif oh_ver == 2:
            config = config_boss_v2
    elif gbt == "sub":
        if oh_ver == 1:
            config = config_sub_v1
        elif oh_ver == 2:
            config = config_sub_v2

    # set phase
    GBT_ELINK_SAMPLE_PHASE_BASE_REG = -9999
    if oh_ver == 1:
        GBT_ELINK_SAMPLE_PHASE_BASE_REG = 0x0CC
    elif oh_ver == 2:
        GBT_ELINK_SAMPLE_PHASE_BASE_REG = 0x0D0
    addr = GBT_ELINK_SAMPLE_PHASE_BASE_REG + sbit_elink
    value = (config[addr] & 0x0f) | (phase << 4)
    #value = (mpeek(addr) & 0x0f) | (phase << 4)

    gem_utils.check_gbt_link_ready(oh_select, gbt_select)
    mpoke(addr, value)
    sleep(0.000001)  # writing too fast for CVP13
Beispiel #2
0
def setVfatRxEnable(system, oh_select, vfat, enable, elink):
    gbt, gbt_select, elink_old, gpio = gem_utils.me0_vfat_to_gbt_elink_gpio(
        vfat)
    oh_ver = get_oh_ver(oh_select, gbt_select)

    if gbt == "boss":
        if oh_ver == 1:
            config = config_boss_v1
        elif oh_ver == 2:
            config = config_boss_v2
    elif gbt == "sub":
        if oh_ver == 1:
            config = config_sub_v1
        elif oh_ver == 2:
            config = config_sub_v2

    # disable/enable channel
    GBT_ELINK_SAMPLE_ENABLE_BASE_REG = -9999
    if oh_ver == 1:
        GBT_ELINK_SAMPLE_ENABLE_BASE_REG = 0x0C4
    elif oh_ver == 2:
        GBT_ELINK_SAMPLE_ENABLE_BASE_REG = 0x0C8
    addr = GBT_ELINK_SAMPLE_ENABLE_BASE_REG + int(elink / 4)
    bit = 4 + elink % 4
    mask = (1 << bit)
    value = (config[addr] & (~mask)) | (enable << bit)

    gem_utils.check_gbt_link_ready(oh_select, gbt_select)
    select_ic_link(oh_select, gbt_select)
    if system != "dryrun":
        check_rom_readback(oh_select, gbt_select)
    mpoke(addr, value)
    sleep(0.000001)  # writing too fast for CVP13
Beispiel #3
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 #4
0
def check_lpgbt_ready(ohIdx=None, gbtIdx=None):
    if ohIdx is None or gbtIdx is None:
        print (Colors.RED + "ERROR: OHID and GBTID not specified" + Colors.ENDC)
        rw_terminate()
    oh_ver = get_oh_ver(ohIdx, gbtIdx)
    ready_value = -9999
    if oh_ver == 1:
        ready_value = 18
    elif oh_ver == 2:
        ready_value = 19
    if system == "backend":
        gem_utils.check_gbt_link_ready(ohIdx, gbtIdx)
    if system != "dryrun":
        pusmstate = readReg(getNode("LPGBT.RO.PUSM.PUSMSTATE"))
        if (pusmstate==ready_value):
            print ("lpGBT status is READY")
        else:
            print (Colors.RED + "ERROR: lpGBT is not READY, configure lpGBT first" + Colors.ENDC)
            rw_terminate()
Beispiel #5
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()
Beispiel #6
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 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")