Beispiel #1
0
def vfat_sbit(gem, system, oh_select, vfat_list, nl1a, calpulse_only,
              l1a_bxgap, set_cal_mode, cal_dac, n_allowed_missing_hits):
    print("%s VFAT S-Bit Mapping\n" % gem)

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

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

    # Reading S-bit counter
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    l1a_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")
    calpulse_node = 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 = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_ELINK_SBIT_ME0"
    )  # Node for selecting Elink to count
    channel_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_SBIT_ME0"
    )  # Node for selecting S-bit to count
    elink_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XE_COUNT_ME0")  # S-bit counter for elink
    channel_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XS_COUNT_ME0"
    )  # S-bit counter for specific channel
    reset_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.CTRL.SBIT_TEST_RESET"
    )  # To reset all S-bit counters

    # Configure all VFATs
    for vfat in vfat_list:
        print("Configuring VFAT %02d" % (vfat))
        gbt, gbt_select, elink_daq, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        link_good = read_backend_reg(
            get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" %
                             (oh_select, vfat)))
        sync_err = read_backend_reg(
            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)
            terminate()

        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        write_backend_reg(
            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
        print("")
    print("")

    # Starting VFAT loop
    s_bit_channel_mapping = {}
    for vfat in vfat_list:
        print("Testing VFAT#: %02d" % (vfat))
        print("")
        write_backend_reg(
            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):
            print("Phase scan for S-bits in ELINK# %02d" % (elink))
            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
                    write_backend_reg(ttc_cnt_reset_node, 1)
                    write_backend_reg(reset_sbit_counter_node, 1)

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

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

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

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

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

                    if system != "dryrun" and abs(
                            elink_sbit_counter_final -
                            calpulse_counter) > n_allowed_missing_hits:
                        print(
                            Colors.YELLOW +
                            "WARNING: Elink %02d did not register the correct number of hits on channel %02d"
                            % (elink, channel) + Colors.ENDC)
                        s_bit_channel_mapping[vfat][elink][channel] = -9999
                        break
                    channel_sbit_counter_final[sbit] = read_backend_reg(
                        channel_sbit_counter_node)

                    if abs(channel_sbit_counter_final[sbit] -
                           calpulse_counter) <= n_allowed_missing_hits:
                        if sbit_channel_match == 1:
                            print(
                                Colors.YELLOW +
                                "WARNING: Multiple S-bits registered hits for calpulse on channel %02d"
                                % (channel) + Colors.ENDC)
                            s_bit_channel_mapping[vfat][elink][channel] = -9999
                            break
                        if s_bit_matches[sbit] >= 2:
                            print(
                                Colors.YELLOW +
                                "WARNING: S-bit %02d already matched to 2 channels"
                                % (sbit) + Colors.ENDC)
                            s_bit_channel_mapping[vfat][elink][channel] = -9999
                            break
                        if s_bit_matches[sbit] == 1:
                            if s_bit_channel_mapping[vfat][elink][channel -
                                                                  1] != sbit:
                                print(
                                    Colors.YELLOW +
                                    "WARNING: S-bit %02d matched to a different channel than the previous one"
                                    % (sbit) + Colors.ENDC)
                                s_bit_channel_mapping[vfat][elink][
                                    channel] = -9999
                                break
                            if channel % 2 == 0:
                                print(
                                    Colors.YELLOW +
                                    "WARNING: S-bit %02d already matched to an earlier odd numbered channel"
                                    % (sbit) + Colors.ENDC)
                                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

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

            print("")
        # End of Elink loop
        print("")
    # End of VFAT loop

    # Unconfigure all VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %02d" % (vfat))
        configureVfat(0, vfat, oh_select, 0)
        print("")
    if calpulse_only:
        write_backend_reg(
            get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    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_mapping_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_mapping_results_" % (
        gem, oh_select) + now + ".py"
    filename_data = dataDir + "/%s_OH%d_vfat_sbit_mapping_data_" % (
        gem, oh_select) + now + ".txt"
    with open(filename, "w") as file:
        file.write(json.dumps(s_bit_channel_mapping))
    file_out_data = open(filename_data, "w")

    print("S-bit Mapping Results: \n")
    file_out_data.write("S-bit Mapping Results: \n\n")
    bad_channels_string = Colors.RED + "\n Bad Channels: \n"
    bad_channel_count = 0
    for vfat in s_bit_channel_mapping:
        print("VFAT %02d: " % (vfat))
        file_out_data.write("VFAT %02d: \n" % (vfat))
        for elink in s_bit_channel_mapping[vfat]:
            print("  ELINK %02d: " % (elink))
            file_out_data.write("  ELINK %02d: \n" % (elink))
            for channel in s_bit_channel_mapping[vfat][elink]:
                if s_bit_channel_mapping[vfat][elink][channel] == -9999:
                    print(Colors.RED + "    Channel %02d:  S-bit %02d" %
                          (channel,
                           s_bit_channel_mapping[vfat][elink][channel]) +
                          Colors.ENDC)
                    file_out_data.write(Colors.RED +
                                        "    Channel %02d:  S-bit %02d\n" %
                                        (channel, s_bit_channel_mapping[vfat]
                                         [elink][channel]) + Colors.ENDC)
                    bad_channels_string += "  VFAT %02d, Elink %02d, Channel %02d\n" % (
                        vfat, elink, channel)
                    bad_channel_count += 1
                else:
                    print(Colors.GREEN + "    Channel %02d:  S-bit %02d" %
                          (channel,
                           s_bit_channel_mapping[vfat][elink][channel]) +
                          Colors.ENDC)
                    file_out_data.write(Colors.GREEN +
                                        "    Channel %02d:  S-bit %02d\n" %
                                        (channel, s_bit_channel_mapping[vfat]
                                         [elink][channel]) + Colors.ENDC)
        print("")
        file_out_data.write("\n")
    bad_channels_string += "\n" + Colors.ENDC
    if bad_channel_count != 0:
        print(bad_channels_string)
        file_out_data.write(bad_channels_string)
    else:
        print(Colors.GREEN + "No Bad Channels in Mapping\n" + Colors.ENDC)
        file_out_data.write(Colors.GREEN + "No Bad Channels in Mapping\n\n" +
                            Colors.ENDC)

    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    print("\nS-bit mapping done\n")
    file_out_data.close()
Beispiel #2
0
def vfat_daq(gem, system, oh_select, vfat_list, channel_list, step, runtime, l1a_bxgap, parallel, all, verbose):

    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_daq_noise_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_daq_noise_"%(gem,oh_select) + now + ".txt"
    file_out = open(filename,"w+")
    file_out.write("vfat    channel    threshold    fired    time\n")

    gem_link_reset()
    global_reset()
    sleep(0.1)

    daq_data = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask all channels and disable calpulsing

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

        daq_data[vfat] = {}
        for channel in channel_list:
            daq_data[vfat][channel] = {}
            for thr in range(0,256,step):
                daq_data[vfat][channel][thr] = {}
                daq_data[vfat][channel][thr]["time"] = -9999
                daq_data[vfat][channel][thr]["fired"] = -9999

    sleep(1)

    # Configure TTC generator
    #write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.SINGLE_HARD_RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"), l1a_bxgap)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"), 0)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 25)

    # Setup the DAQ monitor
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_GLOBAL_OR"), 0)
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.OH_SELECT"), oh_select)
    daq_monitor_reset_node = get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.RESET")
    daq_monitor_enable_node = get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE")
    daq_monitor_select_node = get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_SELECT")

    dac_node = {}
    daq_monitor_event_count_node = {}
    daq_monitor_fire_count_node = {}
    dac = "CFG_THR_ARM_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s"%(oh_select, vfat, dac))
        daq_monitor_event_count_node[vfat] = get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.GOOD_EVENTS_COUNT"%(vfat))
        daq_monitor_fire_count_node[vfat] = get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.CHANNEL_FIRE_COUNT"%(vfat))

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")

    print ("\nRunning Sbit Noise Scans for VFATs:")
    print (vfat_list)
    print ("")

    initial_thr = {}
    for vfat in vfat_list:
        initial_thr[vfat] = read_backend_reg(dac_node[vfat])
        if parallel:
            print ("Unmasking all channels in all VFATs")
            # Unmask channels for this vfat
            for channel in range(0,128):
                enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask channels

    # Looping over channels
    for channel in channel_list:
        if all:
            for vfat in vfat_list:
                for thr in range(0,256,step):
                    daq_data[vfat][channel][thr]["fired"] = 0
                    daq_data[vfat][channel][thr]["time"] = runtime
            continue

        if channel == "all":
            continue
        print ("Channel: %d"%channel)
        for vfat in vfat_list:
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask channel
        write_backend_reg(daq_monitor_select_node, channel)

        # Looping over threshold
        for thr in range(0,256,step):
            if verbose:
                print ("    Threshold: %d"%thr)
            for vfat in vfat_list:
                write_backend_reg(dac_node[vfat], thr)
            sleep(1e-3)

            write_backend_reg(daq_monitor_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 1)

            # Start the cyclic generator
            write_backend_reg(ttc_cyclic_start_node, 1)
            sleep(runtime)
            # Stop the cyclic generator
            write_backend_reg(ttc_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 0)

            # Looping over VFATs
            for vfat in vfat_list:
                #daq_data[vfat][channel][thr]["events"] = read_backend_reg(daq_monitor_event_count_node[vfat])
                daq_data[vfat][channel][thr]["fired"] = read_backend_reg(daq_monitor_fire_count_node[vfat])
                daq_data[vfat][channel][thr]["time"] = runtime
            # End of VFAT loop

        # Mask again channels
        if not parallel:
            for vfat in vfat_list:
                enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask channel

        for vfat in vfat_list:
            write_backend_reg(dac_node[vfat], initial_thr[vfat])
        sleep(1e-3)
        #print ("")

    # End of channel loop
    print ("")

    # Rate counters for entire VFATs
    print ("All VFATs, Channels: All")
    write_backend_reg(daq_monitor_select_node, 0)
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_GLOBAL_OR"), 1)
    for vfat in vfat_list:
        # Unmask channels for this vfat
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask channels
    for thr in range(0,256,step):
        print ("  Threshold: %d"%thr)
        for vfat in vfat_list:
            write_backend_reg(dac_node[vfat], thr)
            sleep(1e-3)

        write_backend_reg(daq_monitor_reset_node, 1)
        write_backend_reg(daq_monitor_enable_node, 1)
        # Start the cyclic generator
        write_backend_reg(ttc_cyclic_start_node, 1)
        sleep(1.1)
        # Stop the cyclic generator
        write_backend_reg(ttc_reset_node, 1)
        write_backend_reg(daq_monitor_enable_node, 0)

        # Looping over VFATs
        for vfat in vfat_list:
            #daq_data[vfat]["all"][thr]["events"] = read_backend_reg(daq_monitor_event_count_node[vfat])
            daq_data[vfat]["all"][thr]["fired"] = read_backend_reg(daq_monitor_fire_count_node[vfat]) * runtime
            daq_data[vfat]["all"][thr]["time"] = runtime
        # End of VFAT loop

    write_backend_reg(get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_GLOBAL_OR"), 0)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    # Disable channels on VFATs
    for vfat in vfat_list:
        write_backend_reg(dac_node[vfat], initial_thr[vfat])
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask all channels
        configureVfat(0, vfat, oh_select, 0)

    # Writing Results
    for vfat in vfat_list:
        for channel in channel_list:
            for thr in range(0,256,1):
                if thr not in daq_data[vfat][channel]:
                    continue
                if channel != "all":
                    file_out.write("%d    %d    %d    %f    %f\n"%(vfat, channel, thr, daq_data[vfat][channel][thr]["fired"], daq_data[vfat][channel][thr]["time"]))
                else:
                    file_out.write("%d    all    %d    %f    %f\n"%(vfat, thr, daq_data[vfat][channel][thr]["fired"], daq_data[vfat][channel][thr]["time"]))

    print ("")
    file_out.close()
def vfat_sbit(gem, system, oh_select, vfat_list, nl1a, calpulse_only,
              l1a_bxgap, set_cal_mode, cal_dac, s_bit_channel_mapping):
    print("LPGBT VFAT S-Bit Cluster Mapping\n")

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

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

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

    write_backend_reg(
        get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"), oh_select)
    reset_sbit_monitor_node = 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(
            get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.CLUSTER%d" % i))
        cluster_count_nodes.append(
            get_backend_node("BEFE.GEM.TRIGGER.OH%d.CLUSTER_COUNT_%d_CNT" %
                             (oh_select, i)))

    s_bit_cluster_mapping = {}
    for vfat in vfat_list:
        gbt, gbt_select, elink_daq, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        link_good = read_backend_reg(
            get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" %
                             (oh_select, vfat)))
        sync_err = read_backend_reg(
            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)
            terminate()

        # Configure the pulsing VFAT
        print("Configuring VFAT %02d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        write_backend_reg(
            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
        print("")

        s_bit_cluster_mapping[vfat] = {}

    sleep(1)

    # Looping over VFATs
    for vfat in vfat_list:
        print("Testing VFAT#: %02d" % (vfat))
        print("")
        # Looping over all channels
        for channel in range(0, 128):
            elink = int(channel / 16)
            sbit = 0
            if gem == "ME0":
                if str(vfat) not in s_bit_channel_mapping:
                    print(Colors.YELLOW +
                          "    Mapping not present for VFAT %02d" % (vfat) +
                          Colors.ENDC)
                    sbit = -9999
                sbit = s_bit_channel_mapping[str(vfat)][str(elink)][str(
                    channel)]
            s_bit_cluster_mapping[vfat][channel] = {}
            s_bit_cluster_mapping[vfat][channel]["sbit"] = sbit
            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
            write_backend_reg(ttc_cnt_reset_node, 1)
            write_backend_reg(reset_sbit_monitor_node, 1)
            write_backend_reg(reset_sbit_cluster_node, 1)

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

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

            l1a_counter = read_backend_reg(l1a_node)
            calpulse_counter = 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(
                    read_backend_reg(cluster_count_nodes[i]))
                sbit_monitor_value = read_backend_reg(sbit_monitor_nodes[i])
                sbit_cluster_address = sbit_monitor_value & 0x7ff
                sbit_cluster_size = ((sbit_monitor_value >> 12) & 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
        # End of Channel loop
        print("")
    # End of VFAT loop

    for vfat in vfat_list:
        # Unconfigure the pulsing VFAT
        print("Unconfiguring VFAT %02d" % (vfat))
        configureVfat(0, vfat, oh_select, 0)
        print("")
    if calpulse_only:
        write_backend_reg(
            get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    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_monitor_cluster_mapping_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_monitor_cluster_mapping_results_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w")
    file_out.write(
        "VFAT    Channel    Sbit    Cluster_Counts (1-7)    Clusters (Size, Address)\n\n"
    )

    bad_mapping_str = Colors.RED + "Bad mapping for channels: \n"
    bad_mapping_count = 0
    for vfat in s_bit_cluster_mapping:
        for channel in s_bit_cluster_mapping[vfat]:
            result_str = "%02d  %03d  %03d  " % (
                vfat, channel, s_bit_cluster_mapping[vfat][channel]["sbit"])
            multiple_cluster_counts = 0
            for i in range(1, 8):
                result_str += "%d," % s_bit_cluster_mapping[vfat][channel][
                    "cluster_count"][i]
                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
            result_str += "  "
            n_clusters = 0
            large_cluster = 0
            for i in range(0, 8):
                if (s_bit_cluster_mapping[vfat][channel]
                    ["sbit_monitor_cluster_address"][i] == 0x7ff
                        or s_bit_cluster_mapping[vfat][channel]
                    ["sbit_monitor_cluster_size"][i] == 8):
                    continue
                n_clusters += 1
                if s_bit_cluster_mapping[vfat][channel][
                        "sbit_monitor_cluster_size"][i] > 1:
                    large_cluster = 1
                result_str += "%d,%03d  " % (
                    s_bit_cluster_mapping[vfat][channel]
                    ["sbit_monitor_cluster_size"][i],
                    s_bit_cluster_mapping[vfat][channel]
                    ["sbit_monitor_cluster_address"][i])
            if n_clusters > 1 or large_cluster == 1 or multiple_cluster_counts == 1:
                bad_mapping_str += "  VFAT %02d, Channel %02d\n" % (vfat,
                                                                    channel)
                bad_mapping_count += 1
            result_str += "\n"
            file_out.write(result_str)
    file_out.close()
    bad_mapping_str += "\n" + Colors.ENDC
    if bad_mapping_count != 0:
        print(bad_mapping_str)
    else:
        print(Colors.GREEN + "No Bad Mapping for Channels\n" + Colors.ENDC)

    print("S-bit Monitor Cluster Mapping Results written in file: %s \n" %
          filename)

    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    print("\nS-bit cluster mapping done\n")
Beispiel #4
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 #5
0
def vfat_crosstalk(gem, system, oh_select, vfat_list, set_cal_mode, cal_dac,
                   nl1a, l1a_bxgap):

    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_daq_crosstalk_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_crosstalk_caldac%d_" % (
        gem, oh_select, cal_dac) + now + "_data.txt"
    file_out = open(filename, "w+")
    file_out.write("vfat    channel_inj    channel_read    fired    events\n")

    gem_link_reset()
    global_reset()
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    sleep(0.1)

    daq_data = {}
    cal_mode = {}
    channel_list = range(0, 128)
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_LATENCY" %
                             (oh_select, vfat)), 18)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)

        for channel in channel_list:
            enableVfatchannel(vfat, oh_select, channel, 0,
                              0)  # unmask all channels and disable calpulsing
        cal_mode[vfat] = read_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)))

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

        daq_data[vfat] = {}
        for channel_inj in channel_list:
            daq_data[vfat][channel_inj] = {}
            for channel_read in channel_list:
                daq_data[vfat][channel_inj][channel_read] = {}
                daq_data[vfat][channel_inj][channel_read]["events"] = -9999
                daq_data[vfat][channel_inj][channel_read]["fired"] = -9999

    sleep(1)

    # Configure TTC generator
    #write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.SINGLE_HARD_RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"), l1a_bxgap)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"), nl1a)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"),
        25)

    # Setup the DAQ monitor
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE"), 1)
    write_backend_reg(
        get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_GLOBAL_OR"),
        0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.OH_SELECT"),
        oh_select)
    daq_monitor_reset_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.RESET")
    daq_monitor_enable_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE")
    daq_monitor_select_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_SELECT")

    daq_monitor_event_count_node = {}
    daq_monitor_fire_count_node = {}
    dac = "CFG_CAL_DAC"
    for vfat in vfat_list:
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s" %
                             (oh_select, vfat, dac)), cal_dac)
        daq_monitor_event_count_node[vfat] = get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.GOOD_EVENTS_COUNT" %
            (vfat))
        daq_monitor_fire_count_node[vfat] = get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.CHANNEL_FIRE_COUNT" %
            (vfat))

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")

    print("\nRunning Crosstalk Scan for %.2e L1A cycles for VFATs:" % (nl1a))
    print(vfat_list)
    print("")

    # Looping over channels to be injected
    for channel_inj in channel_list:
        print("Channel Injected: %d" % channel_inj)
        for vfat in vfat_list:
            enableVfatchannel(vfat, oh_select, channel_inj, 0,
                              1)  # enable calpulsing

        # Looping over channels to be read
        for channel_read in channel_list:
            write_backend_reg(daq_monitor_select_node, channel_read)
            write_backend_reg(daq_monitor_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 1)

            # Start the cyclic generator
            write_backend_reg(ttc_cyclic_start_node, 1)
            cyclic_running = 1
            while (cyclic_running):
                cyclic_running = read_backend_reg(cyclic_running_node)
            # Stop the cyclic generator
            write_backend_reg(ttc_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 0)

            # Looping over VFATs
            for vfat in vfat_list:
                daq_data[vfat][channel_inj][channel_read][
                    "events"] = read_backend_reg(
                        daq_monitor_event_count_node[vfat])
                daq_data[vfat][channel_inj][channel_read][
                    "fired"] = read_backend_reg(
                        daq_monitor_fire_count_node[vfat])
            # End of VFAT loop
        # End of read channel loop

        for vfat in vfat_list:
            enableVfatchannel(vfat, oh_select, channel_inj, 0,
                              0)  # disable calpulsing
    # End of injected channel loop
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
    print("")

    # Disable channels on VFATs
    for vfat in vfat_list:
        enable_channel = 0
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0, 128):
            enableVfatchannel(
                vfat, oh_select, channel, 0,
                0)  # disable calpulsing on all channels for this VFAT
        configureVfat(0, vfat, oh_select, 0)

    # Writing Results
    cross_talk_obs = 0
    filename_result = dataDir + "/%s_OH%d_vfat_crosstalk_caldac%d_" % (
        gem, oh_select, cal_dac) + now + "_result.txt"
    file_result_out = open(filename_result, "w+")
    print("\nCross Talk Results:\n")
    file_result_out.write("Cross Talk Results:\n")
    for vfat in vfat_list:
        for channel_inj in channel_list:
            crosstalk_channel_list = ""
            for channel_read in channel_list:
                if channel_read != channel_inj and daq_data[vfat][channel_inj][
                        channel_read]["fired"] > 0:
                    crosstalk_channel_list += " %d," % channel_read
                file_out.write(
                    "%d    %d    %d    %d    %d\n" %
                    (vfat, channel_inj, channel_read,
                     daq_data[vfat][channel_inj][channel_read]["fired"],
                     daq_data[vfat][channel_inj][channel_read]["events"]))
            if crosstalk_channel_list != "":
                print("  VFAT %d, Cross Talk for Channel %d in channels: %s" %
                      (vfat, channel_inj, crosstalk_channel_list))
                file_result_out.write(
                    "  VFAT %d, Cross Talk for Channel %d in channels: %s\n" %
                    (vfat, channel_inj, crosstalk_channel_list))
                cross_talk_obs += 1
    if cross_talk_obs == 0:
        print(Colors.GREEN + "No Cross Talk observed between channels" +
              Colors.ENDC)
        file_result_out.write("No Cross Talk observed between channels\n")

    print("")
    file_out.close()
    file_result_out.close()
Beispiel #6
0
def vfat_sbit(gem, system, oh_select, vfat, elink_list, channel_list,
              sbit_list, parallel, set_cal_mode, cal_dac, nl1a, calpulse_only,
              runtime, l1a_bxgap):

    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_test_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(" ", "_")
    file_out = open(
        dataDir + "/%s_OH%d_vfat_sbit_test_output_" % (gem, oh_select) + now +
        ".txt", "w")
    print("%s VFAT S-Bit Test\n" % gem)
    file_out.write("%s VFAT S-Bit Test\n\n" % gem)

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

    gbt, gbt_select, elink_daq, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
    print("Testing VFAT#: %02d\n" % (vfat))
    file_out.write("Testing VFAT#: %02d\n\n")

    check_gbt_link_ready(oh_select, gbt_select)
    link_good = read_backend_reg(
        get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" %
                         (oh_select, vfat)))
    sync_err = read_backend_reg(
        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)
        terminate()

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

    # Reading S-bit counter
    if nl1a != 0:
        print("\nReading S-bit counter for %d L1A cycles\n" % (nl1a))
        file_out.write("\nReading S-bit counter for %d L1A cycles\n\n" %
                       (nl1a))
    else:
        print("\nReading S-bit counter for %.2f minutes\n" % (runtime))
        file_out.write("\nReading S-bit counter for %.2f minutes\n\n" %
                       (runtime))
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    l1a_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")
    calpulse_node = 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)
    write_backend_reg(
        get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_VFAT_SBIT_ME0"),
        vfat)  # Select VFAT for reading S-bits
    elink_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_ELINK_SBIT_ME0"
    )  # Node for selecting Elink to count
    channel_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_SBIT_ME0"
    )  # Node for selecting S-bit to count
    elink_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XE_COUNT_ME0")  # S-bit counter for elink
    channel_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XS_COUNT_ME0"
    )  # S-bit counter for specific channel
    reset_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.CTRL.SBIT_TEST_RESET"
    )  # To reset all S-bit counters
    reset_sbit_monitor_node = get_backend_node(
        "BEFE.GEM.TRIGGER.SBIT_MONITOR.RESET")  # To reset S-bit Monitor

    elink_sbit_counter = 0
    channel_sbit_counter = 0
    elink_sbit_counter_list = {}
    channel_sbit_counter_list = {}
    l1a_counter_list = {}
    calpulse_counter_list = {}

    l1a_rate = 1e9 / (l1a_bxgap * 25)  # in Hz
    efficiency = 1
    if l1a_rate > 1e6 * 0.5:
        efficiency = 0.977

    # Configure the pulsing VFAT
    print("Configuring VFAT %02d" % (vfat))
    file_out.write("Configuring VFAT %02d\n" % (vfat))
    configureVfat(1, vfat, oh_select, 0)
    if set_cal_mode == "voltage":
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)), 1)
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                             (oh_select, vfat)), 200)
    elif set_cal_mode == "current":
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)), 2)
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                             (oh_select, vfat)), 0)
    else:
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)), 0)
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                             (oh_select, vfat)), 0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DAC" %
                         (oh_select, vfat)), cal_dac)

    if parallel == "all":
        print("Injecting charge in all channels in parallel\n")
        file_out.write("Injecting charge in all channels in parallel\n\n")
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 0,
                              1)  # unmask channel and enable calpulsing
    elif parallel == "select":
        print("Injecting charge in selected channels in parallel\n")
        file_out.write("Injecting charge in selected channels in parallel\n\n")
        for elink in elink_list:
            for channel in channel_list[elink]:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    else:
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 1,
                              0)  # mask this channel and disable calpulsing

    sleep(1)

    for elink in elink_list:
        print("Channel List in ELINK# %02d:" % (elink))
        file_out.write("Channel List in ELINK# %02d:\n" % (elink))
        print(channel_list[elink])
        for channel in channel_list[elink]:
            file_out.write(str(channel) + "  ")
        file_out.write("\n")
        print("Reading Sbit List in ELINK# %02d:" % (elink))
        file_out.write("Reading Sbit List in ELINK# %02d:\n" % (elink))
        print(sbit_list[elink])
        for sbit in sbit_list[elink]:
            file_out.write(str(sbit) + "  ")
        file_out.write("\n")
        print("")
        file_out.write("\n")

        elink_sbit_counter_list[elink] = {}
        channel_sbit_counter_list[elink] = {}
        l1a_counter_list[elink] = {}
        calpulse_counter_list[elink] = {}

        for channel, sbit_read in zip(channel_list[elink], sbit_list[elink]):
            # Enabling the pulsing channel
            if parallel is None:
                print("Enabling pulsing on channel %02d in ELINK# %02d:" %
                      (channel, elink))
                file_out.write(
                    "Enabling pulsing on channel %02d in ELINK# %02d:\n" %
                    (channel, elink))
                enableVfatchannel(
                    vfat, oh_select, channel, 0,
                    1)  # unmask this channel and enable calpulsing

            write_backend_reg(elink_sbit_select_node,
                              elink)  # Select elink for S-bit counter
            write_backend_reg(channel_sbit_select_node,
                              sbit_read)  # Select S-bit for S-bit counter

            # Reset L1A, CalPulse and S-bit counters
            write_backend_reg(ttc_cnt_reset_node, 1)
            write_backend_reg(reset_sbit_counter_node, 1)
            write_backend_reg(reset_sbit_monitor_node, 1)

            # Start the cyclic generator
            print("ELINK# %02d, Channel %02d: Start L1A and Calpulsing cycle" %
                  (elink, channel))
            file_out.write(
                "ELINK# %02d, Channel %02d: Start L1A and Calpulsing cycle\n" %
                (elink, channel))
            write_backend_reg(
                get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_START"), 1)

            cyclic_running = read_backend_reg(cyclic_running_node)
            nl1a_reg_cycles = 0
            l1a_counter = 0
            t0 = time()
            time_prev = t0
            if nl1a != 0:
                while cyclic_running:
                    cyclic_running = read_backend_reg(cyclic_running_node)
                    time_passed = (time() - time_prev) / 60.0
                    if time_passed >= 1:
                        elink_sbit_counter = read_backend_reg(
                            elink_sbit_counter_node)
                        channel_sbit_counter = read_backend_reg(
                            channel_sbit_counter_node)
                        expected_l1a = int(l1a_rate * (time() - t0) *
                                           efficiency)
                        if (read_backend_reg(l1a_node) < l1a_counter):
                            #nl1a_reg_cycles = int(expected_l1a/(2**32))
                            nl1a_reg_cycles += 1
                        l1a_counter = read_backend_reg(l1a_node)
                        calpulse_counter = read_backend_reg(calpulse_node)
                        real_l1a_counter = nl1a_reg_cycles * (2**
                                                              32) + l1a_counter
                        real_calpulse_counter = nl1a_reg_cycles * (
                            2**32) + calpulse_counter
                        print(
                            "Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e,  S-bit counter for Elink %02d = %.2e,  S-bit counter for Channel %02d = %.2e"
                            %
                            ((time() - t0) / 60.0, real_l1a_counter,
                             real_calpulse_counter, elink, elink_sbit_counter,
                             channel, channel_sbit_counter))
                        file_out.write(
                            "Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e,  S-bit counter for Elink %02d = %.2e,  S-bit counter for Channel %02d = %.2e"
                            %
                            ((time() - t0) / 60.0, real_l1a_counter,
                             real_calpulse_counter, elink, elink_sbit_counter,
                             channel, channel_sbit_counter))
                        time_prev = time()
            else:
                while ((time() - t0) / 60.0) < runtime:
                    time_passed = (time() - time_prev) / 60.0
                    if time_passed >= 1:
                        elink_sbit_counter = read_backend_reg(
                            elink_sbit_counter_node)
                        channel_sbit_counter = read_backend_reg(
                            channel_sbit_counter_node)
                        expected_l1a = int(l1a_rate * (time() - t0) *
                                           efficiency)
                        if (read_backend_reg(l1a_node) < l1a_counter):
                            #nl1a_reg_cycles = int(expected_l1a/(2**32))
                            nl1a_reg_cycles += 1
                        l1a_counter = read_backend_reg(l1a_node)
                        calpulse_counter = read_backend_reg(calpulse_node)
                        real_l1a_counter = nl1a_reg_cycles * (2**
                                                              32) + l1a_counter
                        real_calpulse_counter = nl1a_reg_cycles * (
                            2**32) + calpulse_counter
                        print(
                            "Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e,  S-bit counter for Elink %02d = %.2e,  S-bit counter for Channel %02d = %.2e"
                            %
                            ((time() - t0) / 60.0, real_l1a_counter,
                             real_calpulse_counter, elink, elink_sbit_counter,
                             channel, channel_sbit_counter))
                        file_out.write(
                            "Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e,  S-bit counter for Elink %02d = %.2e,  S-bit counter for Channel %02d = %.2e\n"
                            %
                            ((time() - t0) / 60.0, real_l1a_counter,
                             real_calpulse_counter, elink, elink_sbit_counter,
                             channel, channel_sbit_counter))
                        time_prev = time()

            # Stop the cyclic generator
            write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"),
                              1)
            total_time = time() - t0
            print(
                "ELINK# %02d, Channel %02d, S-bit %02d: L1A and Calpulsing cycle completed in %.2f seconds (%.2f minutes)"
                % (elink, channel, sbit_read, total_time, total_time / 60.0))
            file_out.write(
                "ELINK# %02d, Channel %02d, S-bit %02d: L1A and Calpulsing cycle completed in %.2f seconds (%.2f minutes)\n"
                % (elink, channel, sbit_read, total_time, total_time / 60.0))

            # Disabling the pulsing channels
            if parallel is None:
                print("Disabling pulsing on channel %02d in ELINK# %02d:" %
                      (channel, elink))
                file_out.write(
                    "Disabling pulsing on channel %02d in ELINK# %02d:\n" %
                    (channel, elink))
                enableVfatchannel(
                    vfat, oh_select, channel, 1,
                    0)  # mask this channel and disable calpulsing
            print("")
            file_out.write("\n")

            elink_sbit_counter = read_backend_reg(elink_sbit_counter_node)
            channel_sbit_counter = read_backend_reg(channel_sbit_counter_node)
            l1a_counter = read_backend_reg(l1a_node)
            calpulse_counter = read_backend_reg(calpulse_node)
            elink_sbit_counter_list[elink][channel] = elink_sbit_counter
            channel_sbit_counter_list[elink][channel] = channel_sbit_counter
            l1a_counter_list[elink][channel] = l1a_counter
            calpulse_counter_list[elink][channel] = calpulse_counter

        print("")
        file_out.write("\n")
    if calpulse_only:
        write_backend_reg(
            get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    # Unconfigure the pulsing VFAT
    print("Disabling pulsing on all channels in VFAT# %02d" % (vfat))
    file_out.write("Disabling pulsing on all channels in VFAT# %02d\n" %
                   (vfat))
    print("")
    file_out.write("\n")
    for elink in elink_list:
        for channel in range(0, 128):
            enableVfatchannel(
                vfat, oh_select, channel, 0,
                0)  # disable calpulsing on all channels for this VFAT
    print("Unconfiguring VFAT %02d" % (vfat))
    file_out.write("Unconfiguring VFAT %02d\n" % (vfat))
    configureVfat(0, vfat, oh_select, 0)

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

    print("\nS-Bit Error Test Results for VFAT %02d: \n" % (vfat))
    file_out.write("\nS-Bit Error Test Results for VFAT %02d: \n\n" % (vfat))

    expected_l1a = 0
    if nl1a != 0:
        expected_l1a = nl1a
    else:
        expected_l1a = int(l1a_rate * runtime * 60 * efficiency)
    real_l1a_counter = 0
    real_calpulse_counter = 0

    for elink in elink_list:
        n_sbits_elink_expected = 1
        if parallel == "all":
            n_sbits_elink_expected = 8
        elif parallel == "select":
            n_sbits_elink_expected = len(set(sbit_list[elink]))

        for channel, sbit_read in zip(channel_list[elink], sbit_list[elink]):
            s_bit_expected = 0
            if system != "dryrun":
                nl1a_reg_cycles = int(expected_l1a / (2**32))
                real_l1a_counter = nl1a_reg_cycles * (
                    2**32) + l1a_counter_list[elink][channel]
                real_calpulse_counter = nl1a_reg_cycles * (
                    2**32) + calpulse_counter_list[elink][channel]
                if cal_mode == "voltage":
                    s_bit_expected = real_calpulse_counter * 2  # S-bit double counting
                else:
                    s_bit_expected = real_calpulse_counter
                print(
                    "ELINK# %02d Channel %02d S-Bit %02d, Time: %.2f seconds (%.2f minutes), L1A rate: %.2f kHz, Nr. of L1As  (effi=%.3f): %.2e, Nr. of Calpulses: %.2e \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                    % (elink, channel, sbit_read, total_time,
                       total_time / 60.0, l1a_rate / 1000.0, efficiency,
                       real_l1a_counter, real_calpulse_counter,
                       s_bit_expected * n_sbits_elink_expected, s_bit_expected,
                       elink_sbit_counter_list[elink][channel],
                       channel_sbit_counter_list[elink][channel]))
                file_out.write(
                    "ELINK# %02d Channel %02d S-Bit %02d, Time: %.2f seconds (%.2f minutes), L1A rate: %.2f kHz, Nr. of L1As  (effi=%.3f): %.2e, Nr. of Calpulses: %.2e \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                    % (elink, channel, sbit_read, total_time,
                       total_time / 60.0, l1a_rate / 1000.0, efficiency,
                       real_l1a_counter, real_calpulse_counter,
                       s_bit_expected * n_sbits_elink_expected, s_bit_expected,
                       elink_sbit_counter_list[elink][channel],
                       channel_sbit_counter_list[elink][channel]))
            else:
                if nl1a != 0:
                    if cal_mode == "voltage":
                        s_bit_expected = expected_l1a * 2  # S-bit double counting
                    else:
                        s_bit_expected = expected_l1a
                    print(
                        "ELINK# %02d Channel %02d S-Bit %02d, Number of L1A cycles: %.2e, \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                        % (elink, channel, sbit_read, nl1a, s_bit_expected *
                           n_sbits_elink_expected, s_bit_expected,
                           elink_sbit_counter_list[elink][channel],
                           channel_sbit_counter_list[elink][channel]))
                    file_out.write(
                        "ELINK# %02d Channel %02d S-Bit %02d, Number of L1A cycles: %.2e, \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                        % (elink, channel, sbit_read, nl1a, s_bit_expected *
                           n_sbits_elink_expected, s_bit_expected,
                           elink_sbit_counter_list[elink][channel],
                           channel_sbit_counter_list[elink][channel]))
                else:
                    if cal_mode == "voltage":
                        s_bit_expected = expected_l1a * 2  # S-bit double counting
                    else:
                        s_bit_expected = expected_l1a
                    print(
                        "ELINK# %02d Channel %02d S-Bit %02d, Time: %.2f minutes, L1A rate: %.2f kHz, Nr. of L1As (effi=%.3f): %.2e, \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                        % (elink, channel, sbit_read, runtime, l1a_rate /
                           1000.0, efficiency, expected_l1a, s_bit_expected *
                           n_sbits_elink_expected, s_bit_expected,
                           elink_sbit_counter_list[elink][channel],
                           channel_sbit_counter_list[elink][channel]))
                    file_out.write(
                        "ELINK# %02d Channel %02d S-Bit %02d, Time: %.2f minutes, L1A rate: %.2f kHz, Nr. of L1As (effi=%.3f): %.2e, \nS-bits expected for Elink: %.2e, S-bits expected for Channel: %.2e \nS-bit counter for Elink: %.2e, S-bit counter for Channel: %.2e"
                        % (elink, channel, sbit_read, runtime, l1a_rate /
                           1000.0, efficiency, expected_l1a, s_bit_expected *
                           n_sbits_elink_expected, s_bit_expected,
                           elink_sbit_counter_list[elink][channel],
                           channel_sbit_counter_list[elink][channel]))

            # BER for Channel S-bit
            channel_n_err = s_bit_expected - channel_sbit_counter_list[elink][
                channel]
            if s_bit_expected == 0:
                channel_ber = 0
                channel_ber_ul = 0
            else:
                channel_ber = float(channel_n_err) / s_bit_expected
                channel_ber_ul = 1.0 / s_bit_expected
            if channel_ber == 0:
                print(
                    Colors.GREEN +
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d,  Bit Error Ratio (BER) or Hit Loss Ratio < "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}".format(channel_ber_ul) + Colors.ENDC)
                file_out.write(
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d,  Bit Error Ratio (BER) or Hit Loss Ratio < "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}\n".format(channel_ber_ul))
            elif channel_ber > 0:
                print(
                    Colors.YELLOW +
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d (counted less than expected),  Bit Error Ratio (BER) or Hit Loss Ratio = "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}".format(channel_ber) + Colors.ENDC)
                file_out.write(
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d (counted less than expected),,  Bit Error Ratio (BER) or Hit Loss Ratio = "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}\n".format(channel_ber))
            else:
                print(
                    Colors.YELLOW +
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d (counted more than expected),  Bit Error Ratio (BER) or Hit Loss Ratio = "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}".format(channel_ber) + Colors.ENDC)
                file_out.write(
                    "ELINK# %02d Channel %02d S-Bit %02d: Errors = %d (counted more than expected),,  Bit Error Ratio (BER) or Hit Loss Ratio = "
                    % (elink, channel, sbit_read, channel_n_err) +
                    "{:.2e}\n".format(channel_ber))
            print("")
            file_out.write("\n")

    print("\nS-bit testing done\n")
    file_out.write("\nS-bit testing done\n\n")
    file_out.close()
def vfat_sbit(gem, system, oh_select, vfat_list, sbit_list, step, runtime,
              s_bit_channel_mapping, parallel, all, verbose):

    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_noise_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_noise_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w+")
    file_out.write("vfat    sbit    threshold    fired    time\n")

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

    sbit_data = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 1,
                              0)  # mask all channels and disable calpulsing

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

        sbit_data[vfat] = {}
        for sbit in sbit_list:
            sbit_data[vfat][sbit] = {}
            for thr in range(0, 256, step):
                sbit_data[vfat][sbit][thr] = {}
                sbit_data[vfat][sbit][thr]["time"] = -9999
                sbit_data[vfat][sbit][thr]["fired"] = -9999

    sleep(1)

    # Nodes for Sbit counters
    write_backend_reg(
        get_backend_node("BEFE.GEM.SBIT_ME0.TEST_SEL_OH_SBIT_ME0"), oh_select)
    vfat_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_VFAT_SBIT_ME0")  # VFAT for reading S-bits
    elink_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_ELINK_SBIT_ME0"
    )  # Node for selecting Elink to count
    channel_sbit_select_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SEL_SBIT_ME0"
    )  # Node for selecting S-bit to count
    elink_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XE_COUNT_ME0")  # S-bit counter for elink
    channel_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.TEST_SBIT0XS_COUNT_ME0"
    )  # S-bit counter for specific channel
    reset_sbit_counter_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.CTRL.SBIT_TEST_RESET"
    )  # To reset all S-bit counters
    reset_sbit_vfat_node = get_backend_node(
        "BEFE.GEM.SBIT_ME0.CTRL.MODULE_RESET"
    )  # To reset VFAT S-bit rate registers

    dac_node = {}
    vfat_counter_node = {}
    dac = "CFG_THR_ARM_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s" %
                                          (oh_select, vfat, dac))
        vfat_counter_node[vfat] = get_backend_node(
            "BEFE.GEM.SBIT_ME0.ME0_VFAT%d_SBIT_RATE" %
            vfat)  # S-bit counter for enitre VFAT

    print("\nRunning Sbit Noise Scans for VFATs:")
    print(vfat_list)
    print("")

    initial_thr = {}
    for vfat in vfat_list:
        initial_thr[vfat] = read_backend_reg(dac_node[vfat])
        if parallel:
            print("Unmasking all channels in all VFATs")
            # Unmask channels for this vfat
            for channel in range(0, 128):
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  0)  # unmask channels
            write_backend_reg(dac_node[vfat], 0)

    # Looping over VFATs
    for vfat in vfat_list:
        if all:
            for sbit in sbit_list:
                for thr in range(0, 256, step):
                    sbit_data[vfat][sbit][thr]["fired"] = 0
                    sbit_data[vfat][sbit][thr]["time"] = runtime
            continue
        print("VFAT: %02d" % vfat)

        # Looping over sbits
        for sbit in sbit_list:
            if sbit == "all":
                continue
            if verbose:
                print("  VFAT: %02d, Sbit: %d" % (vfat, sbit))
            elink = int(sbit / 8)
            channel_list = []
            if str(vfat) not in s_bit_channel_mapping:
                print(Colors.YELLOW + "    Mapping not present for VFAT %02d" %
                      (vfat) + Colors.ENDC)
                continue
            for c in s_bit_channel_mapping[str(vfat)][str(elink)]:
                if sbit == s_bit_channel_mapping[str(vfat)][str(elink)][c]:
                    channel_list.append(int(c))
            if len(channel_list) > 2:
                print(Colors.YELLOW +
                      "Skipping S-bit %02d, more than 2 channels" % sbit +
                      Colors.ENDC)
                continue
            elif len(channel_list) == 1:
                print(Colors.YELLOW +
                      "S-bit %02d has 1 non-working channel" % sbit +
                      Colors.ENDC)
            elif len(channel_list) == 0:
                print(Colors.YELLOW +
                      "Skipping S-bit %02d, missing both channels" % sbit +
                      Colors.ENDC)
                continue
            write_backend_reg(vfat_sbit_select_node, vfat)
            write_backend_reg(channel_sbit_select_node, sbit)

            if not parallel:
                # Unmask channels for this sbit
                for channel in channel_list:
                    enableVfatchannel(vfat, oh_select, channel, 0,
                                      0)  # unmask channels

            # Looping over threshold
            for thr in range(0, 256, step):
                #print ("    Threshold: %d"%thr)
                write_backend_reg(dac_node[vfat], thr)
                sleep(1e-3)

                # Count hits in sbit in given time
                write_backend_reg(reset_sbit_counter_node, 1)
                sleep(runtime)
                sbit_data[vfat][sbit][thr]["fired"] = read_backend_reg(
                    channel_sbit_counter_node)
                sbit_data[vfat][sbit][thr]["time"] = runtime
            # End of threshold loop

            if not parallel:
                # Mask again channels for this sbit
                for channel in channel_list:
                    enableVfatchannel(vfat, oh_select, channel, 1,
                                      0)  # mask channels

        # End of sbits loop
        if parallel:
            write_backend_reg(dac_node[vfat], 0)
        else:
            write_backend_reg(dac_node[vfat], initial_thr[vfat])
        sleep(1e-3)
        print("")
    # End of VFAT loop
    print("")

    if parallel:
        for vfat in vfat_list:
            write_backend_reg(dac_node[vfat], initial_thr[vfat])

    # Rate counters for entire VFATs
    print("All VFATs, Sbit: All")
    for vfat in vfat_list:
        # Unmask channels for this vfat
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 0,
                              0)  # unmask channels
    for thr in range(0, 256, step):
        print("  Threshold: %d" % thr)
        for vfat in vfat_list:
            write_backend_reg(dac_node[vfat], thr)
            sleep(1e-3)
        write_backend_reg(reset_sbit_vfat_node, 1)
        sleep(1.1)
        for vfat in vfat_list:
            sbit_data[vfat]["all"][thr]["fired"] = read_backend_reg(
                vfat_counter_node[vfat]) * runtime
            sbit_data[vfat]["all"][thr]["time"] = runtime

    # Disable channels on VFATs
    for vfat in vfat_list:
        write_backend_reg(dac_node[vfat], initial_thr[vfat])
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 0,
                              0)  # unmask all channels
        configureVfat(0, vfat, oh_select, 0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)

    # Writing Results
    for vfat in vfat_list:
        for sbit in sbit_list:
            for thr in range(0, 256, 1):
                if thr not in sbit_data[vfat][sbit]:
                    continue
                if sbit != "all":
                    file_out.write(
                        "%d    %d    %d    %f    %f\n" %
                        (vfat, sbit, thr, sbit_data[vfat][sbit][thr]["fired"],
                         sbit_data[vfat][sbit][thr]["time"]))
                else:
                    file_out.write(
                        "%d    all    %d    %f    %f\n" %
                        (vfat, thr, sbit_data[vfat][sbit][thr]["fired"],
                         sbit_data[vfat][sbit][thr]["time"]))

    print("")
    file_out.close()
def vfat_sbit(gem, system, oh_select, vfat, elink_list, channel_list, trigger, parallel, set_cal_mode, cal_dac, nl1a, calpulse_only, l1a_bxgap, s_bit_cluster_mapping):
    
    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_cluster_test_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(" ", "_")
    file_out = open(dataDir + "/%s_OH%d_vfat_sbit_cluster_test_output_"%(gem,oh_select) + now + ".txt", "w")
    print ("%s VFAT S-Bit Cluster Test\n"%gem)
    file_out.write("%s VFAT S-Bit Cluster Test\n\n"%gem)

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

    gbt, gbt_select, elink_daq, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
    print ("Testing VFAT#: %02d\n" %(vfat))
    file_out.write("Testing VFAT#: %02d\n\n")
    
    check_gbt_link_ready(oh_select, gbt_select)
    link_good = read_backend_reg(get_backend_node("BEFE.GEM.OH_LINKS.OH%d.VFAT%d.LINK_GOOD" % (oh_select, vfat)))
    sync_err = read_backend_reg(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)
        terminate()

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

    n_bx_fifo = 0
    n_bx_fifo += l1a_bxgap * nl1a
    n_cluster_expected = 0
    if n_bx_fifo <= 512:
        n_cluster_expected = nl1a
        print ("Clusters for all L1A's will be recorded in the FIFO")
        file_out.write("Clusters for all L1A's will be recorded in the FIFO\n")
        #print ("Expecting %d clusters in the FIFO\n"%n_cluster_expected)
        #file_out.write("Expecting %d clusters in the FIFO\n\n"%n_cluster_expected)
    else:
        n_bx_fifo = 512
        n_cluster_expected = (int((n_bx_fifo)/l1a_bxgap))
        print (Colors.YELLOW + "Clusters for all L1A's will not be recorded in the FIFO" + Colors.ENDC)
        file_out.write("Clusters for all L1A's will not be recorded in the FIFO\n")
        #print ("Expecting %d clusters in the FIFO\n"%n_cluster_expected)
        #file_out.write("Expecting %d clusters in the FIFO\n\n"%n_cluster_expected)

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    calpulse_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")
    l1a_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")

    # Nodes for Sbit Monitor
    write_backend_reg(get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"), oh_select)
    reset_sbit_monitor_node = 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(get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.CLUSTER%d"%i))
        cluster_count_nodes.append(get_backend_node("BEFE.GEM.TRIGGER.OH%d.CLUSTER_COUNT_%d_CNT"%(oh_select,i)))
    fifo_empty_sbit_monitor_node = get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.FIFO_EMPTY")
    fifo_en_l1a_trigger_sbit_monitor_node = get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.FIFO_EN_L1A_TRIGGER")
    fifo_en_sbit_trigger_sbit_monitor_node = get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.FIFO_EN_SBIT_TRIGGER")
    trigger_delay_sbit_monitor_node = get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.FIFO_TRIGGER_DELAY")
    fifo_data_sbit_monitor_node = get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.FIFO_DATA")

    l1a_rate = 1e9/(l1a_bxgap * 25) # in Hz
    efficiency = 1
    if l1a_rate > 1e6 * 0.5:
        efficiency = 0.977

    # Configure the pulsing VFAT
    print("Configuring VFAT %02d" % (vfat))
    file_out.write("Configuring VFAT %02d\n" % (vfat))
    configureVfat(1, vfat, oh_select, 0)
    if set_cal_mode == "voltage":
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 1)
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 200)
    elif set_cal_mode == "current":
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 2)
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 0)
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)
    write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DAC"% (oh_select, vfat)), cal_dac)

    if parallel == "all":
        print ("Injecting charge in all channels in parallel\n")
        file_out.write("Injecting charge in all channels in parallel\n\n")
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 0, 1) # unmask channel and enable calpulsing
    elif parallel == "select":
        print ("Injecting charge in selected channels in parallel\n")
        file_out.write("Injecting charge in selected channels in parallel\n\n")
        for elink in elink_list:
            for channel in channel_list[elink]:
                enableVfatchannel(vfat, oh_select, channel, 0, 1) # unmask channel and enable calpulsing
    else:
        for channel in range(0, 128):
            enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask this channel and disable calpulsing

    sleep(1)

    # Looping over Elinks
    for elink in elink_list:
        print ("Channel List in ELINK# %02d:" %(elink))
        file_out.write("Channel List in ELINK# %02d:\n" %(elink))
        print (channel_list[elink])
        for channel in channel_list[elink]:
            file_out.write(str(channel) + "  ")
        file_out.write("\n")
        print ("")
        file_out.write("\n")

        # Looping over channels
        for channel in channel_list[elink]:
            if vfat not in s_bit_cluster_mapping:
                print (Colors.YELLOW + "    Mapping not present for VFAT %02d"%(vfat) + Colors.ENDC)
                continue
            if s_bit_cluster_mapping[vfat][channel]["cluster_address"] == -9999:
                print (Colors.YELLOW + "    Bad channel (from S-bit cluster mapping) %02d on VFAT %02d"%(channel,vfat) + Colors.ENDC)
                continue
            # Enabling the pulsing channel
            if parallel is None:
                print("Enabling pulsing on channel %02d in ELINK# %02d:" % (channel, elink))
                file_out.write("Enabling pulsing on channel %02d in ELINK# %02d:\n" % (channel, elink))
                enableVfatchannel(vfat, oh_select, channel, 0, 1) # unmask this channel and enable calpulsing

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

            # Setting Trigger Delay
            write_backend_reg(trigger_delay_sbit_monitor_node, 512)

            # Start the cyclic generator
            print ("ELINK# %02d, Channel %02d: Start L1A and Calpulsing cycle"%(elink, channel))
            file_out.write("ELINK# %02d, Channel %02d: Start L1A and Calpulsing cycle\n"%(elink, channel))
            write_backend_reg(ttc_cyclic_start_node, 1)

            # Setting Trigger Enable
            if trigger == "l1a":
                write_backend_reg(fifo_en_l1a_trigger_sbit_monitor_node, 1)
            elif trigger == "sbit":
                write_backend_reg(fifo_en_sbit_trigger_sbit_monitor_node, 1)

            cyclic_running = 1
            t0 = time()
            while (cyclic_running):
                cyclic_running = read_backend_reg(cyclic_running_node)
            # Stop the cyclic generator
            write_backend_reg(ttc_reset_node, 1)

            # Disabling the pulsing channels
            if parallel is None:
                print("Disabling pulsing on channel %02d in ELINK# %02d:" % (channel, elink))
                file_out.write("Disabling pulsing on channel %02d in ELINK# %02d:\n" % (channel, elink))
                enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask this channel and disable calpulsing
            print("")
            file_out.write("\n")

            # Reading the Sbit Monitor FIFO
            l1a_counter = read_backend_reg(l1a_node)
            calpulse_counter = read_backend_reg(calpulse_node)
            fifo_empty = read_backend_reg(fifo_empty_sbit_monitor_node)
            expected_cluster_size = 0
            expected_cluster_pos = 0
            if parallel:
                expected_cluster_size = len(channel_list)
                expected_cluster_pos = s_bit_cluster_mapping[vfat][min(channel_list)]["cluster_address"]
            else:
                expected_cluster_size = 1
                expected_cluster_pos = s_bit_cluster_mapping[vfat][channel]["cluster_address"]
            n_clusters = 0
            #n_clusters_error = 0
            n_cluster_size_error = 0
            n_cluster_pos_error = 0
            n = -1
            nbx = -1
            status_str = ""
            min_cluster = 0

            while (fifo_empty == 0):
                fifo_data = read_backend_reg(fifo_data_sbit_monitor_node)
                cluster1_sbit_monitor_value = fifo_data & 0x0000ffff
                cluster1_sbit_cluster_address = cluster1_sbit_monitor_value & 0x7ff
                cluster1_sbit_cluster_size = ((cluster1_sbit_monitor_value >> 12) & 0x7) + 1
                cluster1_l1a = cluster1_sbit_monitor_value >> 15

                cluster2_sbit_monitor_value = (fifo_data >> 4) & 0x0000ffff
                cluster2_sbit_cluster_address = cluster2_sbit_monitor_value & 0x7ff
                cluster2_sbit_cluster_size = ((cluster2_sbit_monitor_value >> 12) & 0x7) + 1
                cluster2_l1a = cluster2_sbit_monitor_value >> 15

                fifo_empty = read_backend_reg(fifo_empty_sbit_monitor_node)

                n += 1
                if n%4==0:
                    nbx += 1
                    n = 0
                    status_str = "BX %d:  \n"%nbx
                    min_cluster = 0

                if cluster1_sbit_cluster_address != 0x7ff and cluster1_sbit_cluster_size != 8:
                    status_str += "  Cluster: %d (size = %d)"%(cluster1_sbit_cluster_address, cluster1_sbit_cluster_size)
                    n_clusters += 1
                    min_cluster = 1
                    if cluster1_sbit_cluster_size != expected_cluster_size:
                        n_cluster_size_error += 1
                    if cluster1_sbit_cluster_address != expected_cluster_pos:
                        n_cluster_pos_error += 1
                if cluster2_sbit_cluster_address != 0x7ff and cluster2_sbit_cluster_size != 8:
                    status_str += "  Cluster: %d (size = %d)"%(cluster2_sbit_cluster_address, cluster2_sbit_cluster_size)
                    n_clusters += 1
                    min_cluster = 1
                    if cluster2_sbit_cluster_size != expected_cluster_size:
                        n_cluster_size_error += 1
                    if cluster2_sbit_cluster_address != expected_cluster_pos:
                        n_cluster_pos_error += 1
                if n%4==0 and min_cluster:
                    print (status_str)
                    file_out.write(status_str + "\n")
            #n_clusters_error = n_clusters - n_cluster_expected

            if trigger == "l1a":
                write_backend_reg(fifo_en_l1a_trigger_sbit_monitor_node, 0)
            elif trigger == "sbit":
                write_backend_reg(fifo_en_sbit_trigger_sbit_monitor_node, 0)

            print ("Time taken: %.2f minutes, L1A_rate = %.2f kHz, L1A counter = %.2e,  Calpulse counter = %.2e\n" % ((time()-t0)/60.0, l1a_rate/1000.0, l1a_counter, calpulse_counter))
            file_out.write("Time taken: %.2f minutes, L1A_rate = %.2f kHz, L1A counter = %.2e,  Calpulse counter = %.2e\n\n" % ((time()-t0)/60.0, l1a_rate/1000.0, l1a_counter, calpulse_counter))

            #if n_clusters_error == 0:
                #print (Colors.GREEN + "Nr. of cluster expected = %d, Nr. of clusters recorded = %d"%(n_cluster_expected, n_clusters) + Colors.ENDC)
            #else:
                #print (Colors.RED + "Nr. of cluster expected = %d, Nr. of clusters recorded = %d"%(n_cluster_expected, n_clusters) + Colors.ENDC)
            print ("Nr. of clusters recorded = %d"%(n_clusters))
            #file_out.write("Nr. of cluster expected = %d, Nr. of clusters recorded = %d\n"%(n_cluster_expected, n_clusters))
            file_out.write("Nr. of clusters recorded = %d"%(n_clusters))
            if n_cluster_size_error == 0:
                print (Colors.GREEN + "Nr. of cluster size mismatches = %d"%n_cluster_size_error + Colors.ENDC)
            else:
                print (Colors.RED + "Nr. of cluster size mismatches = %d"%n_cluster_size_error + Colors.ENDC)
            file_out.write("Nr. of cluster size mismatches = %d"%n_cluster_size_error)
            if n_cluster_pos_error == 0:
                print (Colors.GREEN + "Nr. of cluster position mismatches = %d"%n_cluster_pos_error + Colors.ENDC)
            else:
                print (Colors.RED + "Nr. of cluster position mismatches = %d"%n_cluster_pos_error + Colors.ENDC)
            file_out.write("Nr. of cluster position mismatches = %d"%n_cluster_pos_error)

            print ("")
            file_out.write("\n")
    if calpulse_only:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)

    # Unconfigure the pulsing VFAT
    print("Disabling pulsing on all channels in VFAT# %02d" % (vfat))
    file_out.write("Disabling pulsing on all channels in VFAT# %02d\n" % (vfat))
    print("")
    file_out.write("\n")
    for elink in elink_list:
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # disable calpulsing on all channels for this VFAT
    print("Unconfiguring VFAT %02d" % (vfat))
    file_out.write("Unconfiguring VFAT %02d\n" % (vfat))
    configureVfat(0, vfat, oh_select, 0)

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

    print ("\nS-bit Cluster testing done\n")
    file_out.write("\nS-bit Cluster testing done\n\n")
    file_out.close()
def vfat_sbit(gem, system, oh_select, vfat_list, sbit_list, step, runtime, s_bit_cluster_mapping, sbits_all, verbose):

    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_cluster_noise_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_cluster_noise_"%(gem,oh_select) + now + ".txt"
    file_out = open(filename,"w+")
    file_out.write("vfat    sbit    threshold    fired    time\n")

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

    sbit_data = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask all channels and disable calpulsing

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

        sbit_data[vfat] = {}
        for sbit in sbit_list:
            sbit_data[vfat][sbit] = {}
            for thr in range(0,256,step):
                sbit_data[vfat][sbit][thr] = {}
                sbit_data[vfat][sbit][thr]["time"] = -9999
                sbit_data[vfat][sbit][thr]["fired"] = -9999

    sleep(1)
    
    # Nodes for Sbit counters
    write_backend_reg(get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"), oh_select)
    reset_sbit_monitor_node = 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(get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.CLUSTER%d"%i))
        cluster_count_nodes.append(get_backend_node("BEFE.GEM.TRIGGER.OH%d.CLUSTER_COUNT_%d_CNT"%(oh_select,i)))

    dac_node = {}
    dac = "CFG_THR_ARM_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s"%(oh_select, vfat, dac))

    print ("\nRunning Sbit Noise Scans for VFATs:")
    print (vfat_list)
    print ("")

    # Looping over VFATs
    for vfat in vfat_list:
        print ("VFAT %02d"%(vfat))
        initial_thr = read_backend_reg(dac_node[vfat])

        # Looping over sbits
        for sbit in sbit_list:
            if sbits_all and sbit!="all":
                for thr in range(0,256,step):
                    sbit_data[vfat][sbit][thr]["fired"] = 0
                    sbit_data[vfat][sbit][thr]["time"] = runtime
                continue

            if verbose:
                if sbit=="all":
                    print ("  VFAT: %02d, Sbit: all"%(vfat))
                else:
                    print ("  VFAT: %02d, Sbit: %d"%(vfat, sbit))

            channel_list = []
            if sbit == "all":
                channel_list = range(0,128)
            else:
                if gem == "ME0":
                    if vfat not in s_bit_cluster_mapping:
                        print (Colors.YELLOW + "    Mapping not present for VFAT %02d"%(vfat) + Colors.ENDC)
                        continue
                    for c in s_bit_cluster_mapping[vfat]:
                        if sbit == s_bit_cluster_mapping[vfat][c]["sbit"]:
                            channel_list.append(int(c))
                else:
                    channel_list.append(int(2*sbit))
                    channel_list.append(int(2*sbit)+1)
                if len(channel_list)>2:
                    print (Colors.YELLOW + "Skipping S-bit %02d, more than 2 channels"%sbit + Colors.ENDC)
                    continue
                elif len(channel_list)==1:
                    print (Colors.YELLOW + "S-bit %02d has 1 non-working channel"%sbit + Colors.ENDC)
                elif len(channel_list)==0:
                    print (Colors.YELLOW + "Skipping S-bit %02d, missing both channels"%sbit + Colors.ENDC)
                    continue

            # Unmask channels for this vfat
            for channel in channel_list:
                enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask channels

            # Looping over threshold
            for thr in range(0,256,step):
                #print ("    Threshold: %d"%thr)
                write_backend_reg(dac_node[vfat], thr)
                sleep(1e-3)

                # Count number of clusters for VFATs in given time
                write_backend_reg(reset_sbit_monitor_node, 1)
                write_backend_reg(reset_sbit_cluster_node, 1)
                sleep(runtime)

                cluster_counts = []
                for i in range(0,8):
                    cluster_counts.append(read_backend_reg(cluster_count_nodes[i]))
                cluster_addr_mismatch = 0
                sbit_cluster_address_mismatch = -9999
                for i in range(0,8):
                    sbit_monitor_value = read_backend_reg(sbit_monitor_nodes[i])
                    sbit_cluster_address = sbit_monitor_value & 0x7ff
                    sbit_cluster_size = ((sbit_monitor_value >> 12) & 0x7) + 1
                    if sbit_cluster_address!=0x7ff:
                        cluster_addr_match = 0
                        for channel in channel_list:
                            if sbit_cluster_address == s_bit_cluster_mapping[vfat][channel]["cluster_address"]:
                                cluster_addr_match = 1
                                break
                        if cluster_addr_match == 0:
                            sbit_cluster_address_mismatch = sbit_cluster_address
                            cluster_addr_mismatch = 1
                            break
                if cluster_addr_mismatch == 1:
                    if sbit=="all":
                        print (Colors.YELLOW + "Cluster (address = %d) detected not belonging to VFAT %02d for CFG_THR_ARM_DAC = %d"%(sbit_cluster_address_mismatch, vfat, thr) + Colors.ENDC)
                    else:
                        print (Colors.YELLOW + "Cluster (address = %d) detected not belonging to VFAT %02d Sbit %02d for CFG_THR_ARM_DAC = %d"%(sbit_cluster_address_mismatch, vfat, sbit, thr) + Colors.ENDC)
                    continue

                n_total_clusters = 0
                for i in range (1,8):
                    n_total_clusters += i*cluster_counts[i]

                sbit_data[vfat][sbit][thr]["fired"] = n_total_clusters
                sbit_data[vfat][sbit][thr]["time"] = runtime
                # End of threshold loop

            # Mask channels again for this vfat
            for channel in channel_list:
                enableVfatchannel(vfat, oh_select, channel, 1, 0) # mask channels

        # End of sbits loop
        write_backend_reg(dac_node[vfat], initial_thr)
        sleep(1e-3)
        print ("")
    # End of VFAT loop
    print ("")

    # Disable channels on VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0,128):
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask all channels
        configureVfat(0, vfat, oh_select, 0)
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)

    # Writing Results
    for vfat in vfat_list:
        for sbit in sbit_list:
            for thr in range(0,256,1):
                if thr not in sbit_data[vfat][sbit]:
                    continue
                if sbit == "all":
                    file_out.write("%d    %s    %d    %f    %f\n"%(vfat, sbit, thr, sbit_data[vfat][sbit][thr]["fired"], sbit_data[vfat][sbit][thr]["time"]))
                else:
                    file_out.write("%d    %d    %d    %f    %f\n"%(vfat, sbit, thr, sbit_data[vfat][sbit][thr]["fired"], sbit_data[vfat][sbit][thr]["time"]))

    print ("")
    file_out.close()
Beispiel #10
0
def vfat_scurve(gem, system, oh_select, vfat_list, channel_list, set_cal_mode,
                parallel, threshold, step, nl1a, l1a_bxgap, trim):
    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_daq_scurve_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_scurve_" % (gem,
                                                    oh_select) + now + ".txt"
    file_out = open(filename, "w+")
    file_out.write("vfat    channel    charge    fired    events\n")

    gem_link_reset()
    global_reset()
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    sleep(0.1)

    daq_data = {}
    cal_mode = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_LATENCY" %
                             (oh_select, vfat)), 18)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)

        if threshold != -9999:
            print("Setting threshold = %d (DAC)" % threshold)
            write_backend_reg(
                get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_THR_ARM_DAC" %
                    (oh_select, vfat)), threshold)
        for channel in channel_list:
            enableVfatchannel(vfat, oh_select, channel, 1,
                              0)  # mask all channels and disable calpulsing
        cal_mode[vfat] = read_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)))

        if trim == "up":
            print("Trim settings set to high for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 0, 31)
        elif trim == "down":
            print("Trim settings set to low for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 1, 31)

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

        daq_data[vfat] = {}
        for channel in channel_list:
            daq_data[vfat][channel] = {}
            for c in range(0, 256, step):
                #if cal_mode[vfat] == 1:
                #    charge = 255 - c
                #else:
                charge = c
                daq_data[vfat][channel][charge] = {}
                daq_data[vfat][channel][charge]["events"] = -9999
                daq_data[vfat][channel][charge]["fired"] = -9999

    sleep(1)

    # Configure TTC generator
    #write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.SINGLE_HARD_RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"), l1a_bxgap)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"), nl1a)
    write_backend_reg(
        get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"),
        25)

    # Setup the DAQ monitor
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE"), 1)
    write_backend_reg(
        get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_GLOBAL_OR"),
        0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.OH_SELECT"),
        oh_select)
    daq_monitor_reset_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.RESET")
    daq_monitor_enable_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.ENABLE")
    daq_monitor_select_node = get_backend_node(
        "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.CTRL.VFAT_CHANNEL_SELECT")

    dac_node = {}
    daq_monitor_event_count_node = {}
    daq_monitor_fire_count_node = {}
    dac = "CFG_CAL_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s" %
                                          (oh_select, vfat, dac))
        daq_monitor_event_count_node[vfat] = get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.GOOD_EVENTS_COUNT" %
            (vfat))
        daq_monitor_fire_count_node[vfat] = get_backend_node(
            "BEFE.GEM.GEM_TESTS.VFAT_DAQ_MONITOR.VFAT%d.CHANNEL_FIRE_COUNT" %
            (vfat))

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")

    print("\nRunning SCurves for %.2e L1A cycles for VFATs:" % (nl1a))
    print(vfat_list)
    print("")

    if parallel == "all":
        print("Injecting charge in all channels in parallel\n")
        for vfat in vfat_list:
            for channel in range(0, 128):
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    elif parallel == "select":
        print("Injecting charge in selected channels in parallel\n")
        for vfat in vfat_list:
            for channel in channel_list:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    else:
        print("Injecting charge in channels one at a time\n")

    # Looping over channels
    for channel in channel_list:
        print("Channel: %d" % channel)
        if parallel is None:
            for vfat in vfat_list:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
        write_backend_reg(daq_monitor_select_node, channel)

        # Looping over charge
        for c in range(0, 256, step):
            #if cal_mode[vfat] == 1:
            #    charge = 255 - c
            #else:
            charge = c
            #print ("    Injected Charge: %d"%charge)
            for vfat in vfat_list:
                write_backend_reg(dac_node[vfat], c)

            write_backend_reg(daq_monitor_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 1)

            # Start the cyclic generator
            write_backend_reg(ttc_cyclic_start_node, 1)
            cyclic_running = 1
            while (cyclic_running):
                cyclic_running = read_backend_reg(cyclic_running_node)
            # Stop the cyclic generator
            write_backend_reg(ttc_reset_node, 1)
            write_backend_reg(daq_monitor_enable_node, 0)

            # Looping over VFATs
            for vfat in vfat_list:
                daq_data[vfat][channel][charge]["events"] = read_backend_reg(
                    daq_monitor_event_count_node[vfat])
                daq_data[vfat][channel][charge]["fired"] = read_backend_reg(
                    daq_monitor_fire_count_node[vfat])
            # End of VFAT loop
        # End of charge loop

        if parallel is None:
            for vfat in vfat_list:
                enableVfatchannel(vfat, oh_select, channel, 1,
                                  0)  # mask channel and disable calpulsing
    # End of channel loop
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
    print("")

    # Disable channels on VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0, 128):
            enableVfatchannel(
                vfat, oh_select, channel, 0,
                0)  # disable calpulsing on all channels for this VFAT
        configureVfat(0, vfat, oh_select, 0)

    # Writing Results
    for vfat in vfat_list:
        for channel in channel_list:
            for charge in range(0, 256, 1):
                if charge not in daq_data[vfat][channel]:
                    continue
                file_out.write("%d    %d    %d    %d    %d\n" %
                               (vfat, channel, charge,
                                daq_data[vfat][channel][charge]["fired"],
                                daq_data[vfat][channel][charge]["events"]))

    print("")
    file_out.close()
Beispiel #11
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, channel_list, set_cal_mode,
              parallel, threshold, step, nl1a, calpulse_only, l1a_bxgap, trim,
              s_bit_channel_mapping):

    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_scurve_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_scurve_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w+")
    file_out.write("vfat    channel    charge    fired    events\n")

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

    sbit_data = {}
    cal_mode = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)

        if threshold != -9999:
            print("Setting threshold = %d (DAC)" % threshold)
            write_backend_reg(
                get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_THR_ARM_DAC" %
                    (oh_select, vfat)), threshold)
        for channel in channel_list:
            enableVfatchannel(vfat, oh_select, channel, 1,
                              0)  # mask all channels and disable calpulsing
        cal_mode[vfat] = read_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)))

        if trim == "up":
            print("Trim settings set to high for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 0, 31)
        elif trim == "down":
            print("Trim settings set to low for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 1, 31)

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

        sbit_data[vfat] = {}
        for channel in channel_list:
            sbit_data[vfat][channel] = {}
            for c in range(0, 256, step):
                #if cal_mode[vfat] == 1:
                #    charge = 255 - c
                #else:
                charge = c
                sbit_data[vfat][channel][charge] = {}
                sbit_data[vfat][channel][charge]["events"] = -9999
                sbit_data[vfat][channel][charge]["fired"] = -9999

    sleep(1)

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

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    calpulse_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")

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

    dac_node = {}
    dac = "CFG_CAL_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s" %
                                          (oh_select, vfat, dac))

    print("\nRunning Sbit SCurves for %.2e L1A cycles for VFATs:" % (nl1a))
    print(vfat_list)
    print("")

    if parallel == "all":
        print("Injecting charge in all channels in parallel\n")
        for vfat in vfat_list:
            for channel in range(0, 128):
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    elif parallel == "select":
        print("Injecting charge in selected channels in parallel\n")
        for vfat in vfat_list:
            for channel in channel_list:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    else:
        print("Injecting charge in channels one at a time\n")

    # Looping over VFATs
    for vfat in vfat_list:
        # Looping over channels
        for channel in channel_list:
            print("VFAT: %02d  Channel: %d" % (vfat, channel))
            elink = int(channel / 16)

            if str(vfat) not in s_bit_channel_mapping:
                print(Colors.YELLOW + "    Mapping not present for VFAT %02d" %
                      (vfat) + Colors.ENDC)
                continue
            if s_bit_channel_mapping[str(vfat)][str(elink)][str(
                    channel)] == -9999:
                print(
                    Colors.YELLOW +
                    "    Bad channel (from S-bit mapping) %02d on VFAT %02d" %
                    (channel, vfat) + Colors.ENDC)
                continue
            if parallel is None:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
            write_backend_reg(vfat_sbit_select_node, vfat)
            write_backend_reg(
                channel_sbit_select_node,
                s_bit_channel_mapping[str(vfat)][str(elink)][str(channel)])

            # Looping over charge
            for c in range(0, 256, step):
                #if cal_mode[vfat] == 1:
                #    charge = 255 - c
                #else:
                charge = c
                #print ("    Injected Charge: %d"%charge)
                write_backend_reg(dac_node[vfat], c)

                # Start the cyclic generator
                write_backend_reg(ttc_cnt_reset_node, 1)
                write_backend_reg(reset_sbit_counter_node, 1)
                write_backend_reg(ttc_cyclic_start_node, 1)
                cyclic_running = 1
                while (cyclic_running):
                    cyclic_running = read_backend_reg(cyclic_running_node)
                # Stop the cyclic generator
                write_backend_reg(ttc_reset_node, 1)
                calpulse_counter = read_backend_reg(calpulse_node)

                sbit_data[vfat][channel][charge]["events"] = calpulse_counter
                sbit_data[vfat][channel][charge]["fired"] = read_backend_reg(
                    channel_sbit_counter_node)
            # End of charge loop
            if parallel is None:
                enableVfatchannel(vfat, oh_select, channel, 1,
                                  0)  # mask channel and disable calpulsing
        # End of channel loop
        print("")
    # End of VFAT loop
    if calpulse_only:
        write_backend_reg(
            get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
    print("")

    # Disable channels on VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0, 128):
            enableVfatchannel(
                vfat, oh_select, channel, 0,
                0)  # disable calpulsing on all channels for this VFAT
        configureVfat(0, vfat, oh_select, 0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)

    # Writing Results
    for vfat in vfat_list:
        for channel in channel_list:
            for charge in range(0, 256, 1):
                if charge not in sbit_data[vfat][channel]:
                    continue
                file_out.write("%d    %d    %d    %d    %d\n" %
                               (vfat, channel, charge,
                                sbit_data[vfat][channel][charge]["fired"],
                                sbit_data[vfat][channel][charge]["events"]))

    print("")
    file_out.close()
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")
Beispiel #14
0
def vfat_dac_scan(gem, system, oh_select, vfat_list, dac_list, lower,
                  upper_list, step, niter, adc_ref, vref_list):

    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_dac_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_dac_scan_output_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(
        filename, "w+"
    )  # OH number, DAC register name, VFAT number, dac scan point, value, error
    file_out.write("OH;DAC_reg;vfat;DAC_point;value;error\n")
    file_out.close()
    print("VFAT DAC Scan for VFATs:")
    print(vfat_list)
    print("")

    gem_link_reset()
    sleep(0.1)

    link_good_node = {}
    sync_error_node = {}
    dac_node = {}
    vfat_hyst_en_node = {}
    vfat_cfg_run_node = {}
    vfat_cfg_calmode_node = {}
    vfat_cfg_calselpol_node = {}
    adc_monitor_select_node = {}
    adc0_cached_node = {}
    adc0_update_node = {}
    adc1_cached_node = {}
    adc1_update_node = {}
    dac_scan_results = {}
    dac_scan_errors = {}

    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)

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

        dac_node[vfat] = {}
        for dac in dac_list:
            dac_actual = dac
            if dac in [
                    "CFG_CAL_DAC_I", "CFG_CAL_DAC_V_HIGH", "CFG_CAL_DAC_V_LOW"
            ]:
                dac_actual = "CFG_CAL_DAC"
            dac_node[vfat][dac] = get_backend_node(
                "BEFE.GEM.OH.OH%d.GEB.VFAT%d.%s" %
                (oh_select, vfat, dac_actual))
        vfat_hyst_en_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_EN_HYST" % (oh_select, vfat))
        vfat_cfg_run_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_RUN" % (oh_select, vfat))
        vfat_cfg_calmode_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_CAL_MODE" % (oh_select, vfat))
        vfat_cfg_calselpol_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_CAL_SEL_POL" % (oh_select, vfat))
        adc_monitor_select_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.CFG_MONITOR_SELECT" %
            (oh_select, vfat))
        adc0_cached_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.ADC0_CACHED" % (oh_select, vfat))
        adc0_update_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.ADC0_UPDATE" % (oh_select, vfat))
        adc1_cached_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.ADC1_CACHED" % (oh_select, vfat))
        adc1_update_node[vfat] = get_backend_node(
            "BEFE.GEM.OH.OH%d.GEB.VFAT%d.ADC1_UPDATE" % (oh_select, vfat))

        write_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.CFG_VREF_ADC" %
                             (oh_select, vfat)), vref_list[vfat])

        dac_scan_results[vfat] = {}
        for dac in dac_list:
            dac_scan_results[vfat][dac] = {}
            for reg in range(lower, MAX_DAC_SIZE[dac] + 1, step):
                dac_scan_results[vfat][dac][reg] = -9999

        dac_scan_errors[vfat] = {}
        for dac in dac_list:
            dac_scan_errors[vfat][dac] = {}
            for reg in range(lower, MAX_DAC_SIZE[dac] + 1, step):
                dac_scan_errors[vfat][dac][reg] = -9999

    sleep(1)

    # Loop over VFATs
    for vfat in vfat_list:
        print("VFAT %02d" % vfat)
        #write_backend_reg(vfat_hyst_en_node[vfat], 0) # disable hysteresis for testing the DACs

        # Loop over DACs
        for dac in dac_list:
            print("  Scanning DAC: " + dac)
            upper = upper_list[dac]

            # Setup DAC Monitor
            write_backend_reg(adc_monitor_select_node[vfat],
                              REGISTER_DAC_MONITOR_MAP[dac])

            calmode_initial = read_backend_reg(vfat_cfg_calmode_node[vfat])
            calselpol_initial = read_backend_reg(vfat_cfg_calselpol_node[vfat])
            if dac == "CFG_CAL_DAC_I":
                write_backend_reg(vfat_cfg_calmode_node[vfat], 0x2)
                write_backend_reg(vfat_cfg_calselpol_node[vfat], 0x0)
            elif dac in ["CFG_CAL_DAC_V_HIGH", "CFG_CAL_DAC_V_LOW"]:
                write_backend_reg(vfat_cfg_calmode_node[vfat], 0x1)
                if dac == "CFG_CAL_DAC_V_HIGH":
                    write_backend_reg(vfat_cfg_calselpol_node[vfat], 0x0)
                elif dac == "CFG_CAL_DAC_V_LOW":
                    write_backend_reg(vfat_cfg_calselpol_node[vfat], 0x1)

            # Set VFAT to Run Mode
            #write_backend_reg(vfat_cfg_run_node[vfat], 0x1)

            # Initial value of DAC
            dac_initial = read_backend_reg(dac_node[vfat][dac])

            write_backend_reg(dac_node[vfat][dac], 0x0)
            for ii in range(0, niter):
                if adc_ref == "internal":  # use ADC0
                    adc_update_read = read_backend_reg(
                        adc0_update_node[vfat]
                    )  # read/write to this register triggers a cache update
                    sleep(20e-6)  # sleep for 20 us

            # Looping over DAC values
            for reg in range(lower, upper + 1, step):

                # Set DAC value
                write_backend_reg(dac_node[vfat][dac], reg)

                adc_value = []
                # Taking average
                for i in range(0, niter):
                    if adc_ref == "internal":  # use ADC0
                        adc_update_read = read_backend_reg(
                            adc0_update_node[vfat]
                        )  # read/write to this register triggers a cache update
                        sleep(20e-6)  # sleep for 20 us
                        adc_value.append(
                            read_backend_reg(adc0_cached_node[vfat]))
                    elif adc_ref == "external":  # use ADC1
                        adc_update_read = read_backend_reg(
                            adc1_update_node[vfat]
                        )  # read/write to this register triggers a cache update
                        sleep(20e-6)  # sleep for 20 us
                        adc_value.append(
                            read_backend_reg(adc1_cached_node[vfat]))
                dac_scan_results[vfat][dac][reg] = sum(adc_value) / len(
                    adc_value)
                var = sum([((x - dac_scan_results[vfat][dac][reg])**2)
                           for x in adc_value]) / len(adc_value)
                dac_scan_errors[vfat][dac][reg] = var**0.5

            # Set VFAT to Sleep Mode
            #write_backend_reg(vfat_cfg_run_node[vfat], 0x0)

            # Set back DAC to initial value
            write_backend_reg(dac_node[vfat][dac], dac_initial)
            write_backend_reg(vfat_cfg_calmode_node[vfat], calmode_initial)
            write_backend_reg(vfat_cfg_calselpol_node[vfat], calselpol_initial)

            # Reset DAC Monitor
            write_backend_reg(adc_monitor_select_node[vfat], 0)

            # Writing results in output file
            file_out = open(filename, "a")
            for reg in range(lower, upper + 1, step):
                file_out.write("%d;%s;%d;%d;%d;%i\n" %
                               (oh_select, dac, vfat, reg,
                                dac_scan_results[vfat][dac][reg],
                                dac_scan_errors[vfat][dac][reg]))
            file_out.close()

        #write_backend_reg(vfat_hyst_en_node[vfat], 1)

    print("")
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        configureVfat(0, vfat, oh_select, 0)

    print("")
    print("DAC Scan completed\n")
Beispiel #15
0
def vfat_bert(gem, system, oh_select, vfat_list, set_cal_mode, cal_dac, nl1a, runtime, l1a_bxgap, cl, calpulse):
    
    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_daq_test_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(" ", "_")
    file_out = open(dataDir+"/%s_OH%d_vfat_daq_test_output_"%(gem,oh_select) + now + ".txt", "w+")

    if nl1a!=0:
        print ("VFAT Bit Error Ratio Test with %.2e L1As\n" % (nl1a))
        file_out.write("VFAT Bit Error Ratio Test with %.2e L1As\n\n" % (nl1a))
    elif runtime!=0:
        print ("VFAT Bit Error Ratio Test for %.2f minutes\n" % (runtime))
        file_out.write("VFAT Bit Error Ratio Test for %.2f minutes\n\n" % (runtime))
    errors = {}
    error_rates = {}

    gem_link_reset()
    global_reset()
    write_backend_reg(get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)
    sleep(0.1)

    link_good_node = {}
    sync_error_node = {}
    daq_event_count_node = {}
    daq_crc_error_node = {}
    daq_event_count_final = 24*[0]
    daq_crc_error_count_final = 24*[0]
    daq_event_count_diff = 24*[0]
    daq_crc_error_count_diff = 24*[0]

    l1a_rate = 1e9/(l1a_bxgap * 25) # in Hz
    efficiency = 1
    if l1a_rate > 1e6 * 0.5:
        efficiency = 0.977

    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        file_out.write("Configuring VFAT %d\n" % (vfat))
        if calpulse:
            configureVfat(1, vfat, oh_select, 0)
            for channel in range(128):
                enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask all channels and disable calpulsing
            enableVfatchannel(vfat, oh_select, 0, 0, 1) # enable calpulsing on channel 0 for this VFAT
        else:
            configureVfat(1, vfat, oh_select, 1) # configure with 0 threshold to get noise
            for channel in range(128):
                enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask all channels and disable calpulsing
        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_LATENCY"% (oh_select, vfat)), 18)
        if set_cal_mode == "voltage":
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 1)
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 2)
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)
        else:
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE"% (oh_select, vfat)), 0)
            write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR"% (oh_select, vfat)), 0)

        write_backend_reg(get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DAC"% (oh_select, vfat)), cal_dac)

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

    sleep(1)

    # Configure TTC generator
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 1)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_GAP"), l1a_bxgap)
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_L1A_COUNT"), nl1a)

    if calpulse:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 25)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_CALPULSE_TO_L1A_GAP"), 0) # Disable Calpulsing

    if nl1a != 0:
        print ("\nRunning for %.2e L1A cycles for VFATs:" % (nl1a))
        file_out.write("\nRunning for %.2e L1A cycles for VFATs:\n" % (nl1a))
    else:
        print ("\nRunning for %f minutes for VFATs:" %(runtime))
        file_out.write("\nRunning for %f minutes for VFATs:\n" %(runtime))
    print (vfat_list)
    for vfat in vfat_list:
        file_out.write(str(vfat) + "  ")
    file_out.write("\n")
    print ("")
    file_out.write("\n")
    cyclic_running_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    l1a_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.L1A")
    calpulse_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")

    # Start the cyclic generator
    write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.CYCLIC_START"), 1)

    cyclic_running = read_backend_reg(cyclic_running_node)
    nl1a_reg_cycles = 0
    l1a_counter = 0
    t0 = time()
    time_prev = t0
    if nl1a != 0:
        while cyclic_running:
            cyclic_running = read_backend_reg(cyclic_running_node)
            time_passed = (time()-time_prev)/60.0
            if time_passed >= 1:
                expected_l1a = int(l1a_rate * (time()-t0) * efficiency)
                if (read_backend_reg(l1a_node) < l1a_counter):
                    #nl1a_reg_cycles = int(expected_l1a/(2**32))
                    nl1a_reg_cycles += 1
                l1a_counter = read_backend_reg(l1a_node)
                calpulse_counter = read_backend_reg(calpulse_node)
                real_l1a_counter = nl1a_reg_cycles*(2**32) + l1a_counter
                if calpulse:
                    real_calpulse_counter = nl1a_reg_cycles*(2**32) + calpulse_counter
                else:
                    real_calpulse_counter = calpulse_counter
                #daq_event_count_temp = read_backend_reg(daq_event_count_node[vfat])
                daq_event_count_temp = real_l1a_counter # since DAQ_EVENT_CNT is a 16-bit rolling counter
                print ("Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e, DAQ Events = %.2e" % ((time()-t0)/60.0, real_l1a_counter, real_calpulse_counter, daq_event_count_temp))
                file_out.write("Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e, DAQ Events = %.2e" % ((time()-t0)/60.0, real_l1a_counter, real_calpulse_counter, daq_event_count_temp))
                vfat_results_string = ""
                for vfat in vfat_list:
                    daq_error_count_temp = read_backend_reg(daq_crc_error_node[vfat])
                    vfat_results_string += "VFAT %02d DAQ Errors: %d, "%(vfat, daq_error_count_temp)
                print (vfat_results_string + "\n")
                file_out.write(vfat_results_string + "\n\n")
                time_prev = time()
    else:
        while ((time()-t0)/60.0) < runtime:
            time_passed = (time()-time_prev)/60.0
            if time_passed >= 1:
                expected_l1a = int(l1a_rate * (time()-t0) * efficiency)
                if (read_backend_reg(l1a_node) < l1a_counter):
                    #nl1a_reg_cycles = int(expected_l1a/(2**32))
                    nl1a_reg_cycles += 1
                l1a_counter = read_backend_reg(l1a_node)
                calpulse_counter = read_backend_reg(calpulse_node)
                real_l1a_counter = nl1a_reg_cycles*(2**32) + l1a_counter
                if calpulse:
                    real_calpulse_counter = nl1a_reg_cycles*(2**32) + calpulse_counter
                else:
                    real_calpulse_counter = calpulse_counter
                #daq_event_count_temp = read_backend_reg(daq_event_count_node[vfat])
                daq_event_count_temp = real_l1a_counter # since DAQ_EVENT_CNT is a 16-bit rolling counter
                print ("Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e, DAQ Events = %.2e" % ((time()-t0)/60.0, real_l1a_counter, real_calpulse_counter, daq_event_count_temp))
                file_out.write("Time passed: %.2f minutes, L1A counter = %.2e,  Calpulse counter = %.2e, DAQ Events = %.2e\n" % ((time()-t0)/60.0, real_l1a_counter, real_calpulse_counter, daq_event_count_temp))
                vfat_results_string = ""
                for vfat in vfat_list:
                    daq_error_count_temp = read_backend_reg(daq_crc_error_node[vfat])
                    vfat_results_string += "VFAT %02d DAQ Errors: %d, "%(vfat, daq_error_count_temp)
                print (vfat_results_string + "\n")
                file_out.write(vfat_results_string + "\n\n")
                time_prev = time()

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

    print ("")
    file_out.write("\n")
    total_time = time() - t0
    print ("L1A and Calpulsing cycle completed in %.2f seconds (%.2f minutes) \n"%(total_time, total_time/60.0))
    file_out.write("L1A and Calpulsing cycle completed in %.2f seconds (%.2f minutes) \n\n"%(total_time, total_time/60.0))
    l1a_counter = read_backend_reg(l1a_node)
    calpulse_counter = read_backend_reg(calpulse_node)

    print ("Error test results for DAQ elinks\n")
    file_out.write("Error test results for DAQ elinks\n\n")
    for vfat in vfat_list:
        link_good = read_backend_reg(link_good_node[vfat])
        sync_err = read_backend_reg(sync_error_node[vfat])
        if link_good == 1:
            print (Colors.GREEN + "VFAT#: %02d, link is GOOD"%(vfat) + Colors.ENDC)
            file_out.write("VFAT#: %02d, link is GOOD\n"%(vfat))
        else:
            print (Colors.RED + "VFAT#: %02d, link is BAD"%(vfat) + Colors.ENDC)
            file_out.write("VFAT#: %02d, link is BAD\n"%(vfat))
        if sync_err==0:
            print (Colors.GREEN + "VFAT#: %02d, nr. of sync errors: %d"%(vfat, sync_err) + Colors.ENDC)
            file_out.write("VFAT#: %02d, nr. of sync errors: %d\n"%(vfat, sync_err))
        else:
            print (Colors.RED + "VFAT#: %02d, nr. of sync errors: %d"%(vfat, sync_err) + Colors.ENDC)
            file_out.write("VFAT#: %02d, nr. of sync errors: %d\n"%(vfat, sync_err))

        daq_event_count_final[vfat] = read_backend_reg(daq_event_count_node[vfat])
        daq_crc_error_count_final[vfat] = read_backend_reg(daq_crc_error_node[vfat])
        daq_event_count_diff[vfat] = daq_event_count_final[vfat]
        daq_crc_error_count_diff[vfat] = daq_crc_error_count_final[vfat]

        expected_l1a = 0
        if nl1a != 0:
            expected_l1a = nl1a
        else:
            expected_l1a = int(l1a_rate * runtime * 60 * efficiency)
        real_l1a_counter = 0
        real_calpulse_counter = 0

        if system != "dryrun":
            nl1a_reg_cycles = int(expected_l1a/(2**32))
            real_l1a_counter = nl1a_reg_cycles*(2**32) + l1a_counter
            if calpulse:
                real_calpulse_counter = nl1a_reg_cycles*(2**32) + calpulse_counter
            else:
                real_calpulse_counter = calpulse_counter
            if daq_event_count_diff[vfat] != real_l1a_counter%(2**16):
                print (Colors.YELLOW + "Mismatch between DAQ_EVENT_CNT and L1A counter: %d"%(real_l1a_counter%(2**16) - daq_event_count_diff[vfat]) + Colors.ENDC)
                file_out.write("Mismatch between DAQ_EVENT_CNT and L1A counter: %d\n"%(real_l1a_counter%(2**16) - daq_event_count_diff[vfat]))
            daq_event_count_diff[vfat] = real_l1a_counter # since DAQ_EVENT_CNT is a 16-bit rolling counter
        else:
            if nl1a != 0:
                daq_event_count_diff[vfat] = nl1a
                l1a_counter = nl1a
                real_l1a_counter = nl1a
                if calpulse:
                    calpulse_counter = nl1a
                    real_calpulse_counter = nl1a
                else:
                    calpulse_counter = 0
            else:
                daq_event_count_diff[vfat] = expected_l1a
                l1a_counter = expected_l1a
                real_l1a_counter = expected_l1a
                if calpulse:
                    calpulse_counter = expected_l1a
                    real_calpulse_counter = expected_l1a
                else:
                    calpulse_counter = 0
        print ("VFAT#: %02d, Time: %.2f minutes,  L1A rate: %.2f kHz, Expected L1As (effi=%.3f): %.2e, Nr. of L1As: %.2e,  Nr. of Calpulses: %.2e  \nDAQ Events: %.2e,  DAQ CRC Errors: %d" %(vfat, total_time/60.0, l1a_rate/1000.0, efficiency, expected_l1a, real_l1a_counter, real_calpulse_counter, daq_event_count_diff[vfat], daq_crc_error_count_diff[vfat]))
        file_out.write("VFAT#: %02d, Time: %.2f minutes,  L1A rate: %.2f kHz, Expected L1As (effi=%.3f): %.2e, Nr. of L1As: %.2e,  Nr. of Calpulses: %.2e  \nDAQ Events: %.2e,  DAQ CRC Errors: %d\n" %(vfat, total_time/60.0, l1a_rate/1000.0, efficiency, expected_l1a, real_l1a_counter, real_calpulse_counter, daq_event_count_diff[vfat], daq_crc_error_count_diff[vfat]))

        daq_data_packet_size = 176 # 176 bits 
        cl = float(cl)
        #if daq_event_count_diff[vfat]==0:
        #    ber = 0
        #    ineffi = 0
        #else:
        #    ber = float(daq_crc_error_count_diff[vfat])/(daq_event_count_diff[vfat] * daq_data_packet_size)
        #    ineffi = float(daq_crc_error_count_diff[vfat])/(daq_event_count_diff[vfat])
        ber_ul = (-math.log(1-cl))/(daq_event_count_diff[vfat] * daq_data_packet_size)
        ineffi_ul = (-math.log(1-cl))/(daq_event_count_diff[vfat])
        if daq_crc_error_count_diff[vfat] == 0:
            print (Colors.GREEN + "VFAT#: %02d, Errors = %d,  Bit Error Ratio (BER) < "%(vfat, daq_crc_error_count_diff[vfat]) + "{:.2e}".format(ber_ul) + ", Inefficiency < " + "{:.2e}".format(ineffi_ul) + Colors.ENDC)
            file_out.write("VFAT#: %02d, Errors = %d,  Bit Error Ratio (BER) < "%(vfat, daq_crc_error_count_diff[vfat]) + "{:.2e}\n".format(ber_ul) + ", Inefficiency < " + "{:.2e}".format(ineffi_ul))
        else:
            print (Colors.YELLOW + "VFAT#: %02d, Errors = %d"%(vfat, daq_crc_error_count_diff[vfat]) + Colors.ENDC)
            file_out.write("VFAT#: %02d, Errors = %d\n"%(vfat, daq_crc_error_count_diff[vfat]))
            #print (Colors.YELLOW + "VFAT#: %02d, Errors = %d,  Bit Error Ratio (BER) = "%(vfat, daq_crc_error_count_diff[vfat]) + "{:.2e}".format(ber) + ", Inefficiency = " + "{:.2e}".format(ineffi) + Colors.ENDC)
            #file_out.write("VFAT#: %02d, Errors = %d,  Bit Error Ratio (BER) = "%(vfat, daq_crc_error_count_diff[vfat]) + "{:.2e}\n".format(ber) + ", Inefficiency = " + "{:.2e}".format(ineffi))

            print ("")
            file_out.write("\n")
        print ("")
        file_out.write("\n\n")

    # Disable channels on VFATs
    for vfat in vfat_list:
        enable_channel = 0
        print("Unconfiguring VFAT %d" % (vfat))
        file_out.write("Unconfiguring VFAT %d\n" % (vfat))
        for channel in range(128):
            enableVfatchannel(vfat, oh_select, channel, 0, 0) # unmask all channels and disable calpulsing
        configureVfat(0, vfat, oh_select, 0)

    file_out.close()
Beispiel #16
0
def vfat_sbit(gem, system, oh_select, vfat_list, channel_list, set_cal_mode,
              parallel, threshold, step, nl1a, calpulse_only, l1a_bxgap, trim,
              s_bit_cluster_mapping):
    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_cluster_scurve_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_cluster_scurve_" % (
        gem, oh_select) + now + ".txt"
    file_out = open(filename, "w+")
    file_out.write("vfat    channel    charge    fired    events\n")

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

    sbit_data = {}
    cal_mode = {}
    # Check ready and get nodes
    for vfat in vfat_list:
        gbt, gbt_select, elink, gpio = me0_vfat_to_gbt_elink_gpio(vfat)
        check_gbt_link_ready(oh_select, gbt_select)

        print("Configuring VFAT %d" % (vfat))
        configureVfat(1, vfat, oh_select, 0)
        if set_cal_mode == "voltage":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 1)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 200)
        elif set_cal_mode == "current":
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 2)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)
        else:
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                                 (oh_select, vfat)), 0)
            write_backend_reg(
                get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_DUR" %
                                 (oh_select, vfat)), 0)

        if threshold != -9999:
            print("Setting threshold = %d (DAC)" % threshold)
            write_backend_reg(
                get_backend_node(
                    "BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_THR_ARM_DAC" %
                    (oh_select, vfat)), threshold)
        for channel in channel_list:
            enableVfatchannel(vfat, oh_select, channel, 1,
                              0)  # mask all channels and disable calpulsing
        cal_mode[vfat] = read_backend_reg(
            get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%i.CFG_CAL_MODE" %
                             (oh_select, vfat)))

        if trim == "up":
            print("Trim settings set to high for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 0, 31)
        elif trim == "down":
            print("Trim settings set to low for all channels")
            for channel in channel_list:
                setVfatchannelTrim(vfat, oh_select, channel, 1, 31)

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

        sbit_data[vfat] = {}
        for channel in channel_list:
            sbit_data[vfat][channel] = {}
            for c in range(0, 256, step):
                #if cal_mode[vfat] == 1:
                #    charge = 255 - c
                #else:
                charge = c
                sbit_data[vfat][channel][charge] = {}
                sbit_data[vfat][channel][charge]["events"] = -9999
                sbit_data[vfat][channel][charge]["fired"] = -9999

    sleep(1)

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

    ttc_reset_node = get_backend_node("BEFE.GEM.TTC.GENERATOR.RESET")
    ttc_cyclic_start_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_START")
    cyclic_running_node = get_backend_node(
        "BEFE.GEM.TTC.GENERATOR.CYCLIC_RUNNING")
    calpulse_node = get_backend_node("BEFE.GEM.TTC.CMD_COUNTERS.CALPULSE")

    # Nodes for Sbit counters
    write_backend_reg(
        get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.OH_SELECT"), oh_select)
    reset_sbit_monitor_node = 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(
            get_backend_node("BEFE.GEM.TRIGGER.SBIT_MONITOR.CLUSTER%d" % i))
        cluster_count_nodes.append(
            get_backend_node("BEFE.GEM.TRIGGER.OH%d.CLUSTER_COUNT_%d_CNT" %
                             (oh_select, i)))

    dac_node = {}
    dac = "CFG_CAL_DAC"
    for vfat in vfat_list:
        dac_node[vfat] = get_backend_node("BEFE.GEM.OH.OH%i.GEB.VFAT%d.%s" %
                                          (oh_select, vfat, dac))

    print("\nRunning Sbit SCurves for %.2e L1A cycles for VFATs:" % (nl1a))
    print(vfat_list)
    print("")

    if parallel == "all":
        print("Injecting charge in all channels in parallel\n")
        for vfat in vfat_list:
            for channel in range(0, 128):
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    elif parallel == "select":
        print("Injecting charge in selected channels in parallel\n")
        for vfat in vfat_list:
            for channel in channel_list:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing
    else:
        print("Injecting charge in channels one at a time\n")

    # Looping over VFATs
    for vfat in vfat_list:
        # Looping over channels
        for channel in channel_list:
            print("VFAT: %02d  Channel: %d" % (vfat, channel))

            if vfat not in s_bit_cluster_mapping:
                print(Colors.YELLOW + "    Mapping not present for VFAT %02d" %
                      (vfat) + Colors.ENDC)
                continue
            if s_bit_cluster_mapping[vfat][channel][
                    "cluster_address"] == -9999:
                print(
                    Colors.YELLOW +
                    "    Bad channel (from S-bit cluster mapping) %02d on VFAT %02d"
                    % (channel, vfat) + Colors.ENDC)
                continue
            if parallel is None:
                enableVfatchannel(vfat, oh_select, channel, 0,
                                  1)  # unmask channel and enable calpulsing

            # Looping over charge
            for c in range(0, 256, step):
                #if cal_mode[vfat] == 1:
                #    charge = 255 - c
                #else:
                charge = c
                #print ("    Injected Charge: %d"%charge)
                write_backend_reg(dac_node[vfat], c)

                # Start the cyclic generator
                write_backend_reg(ttc_cnt_reset_node, 1)
                write_backend_reg(reset_sbit_monitor_node, 1)
                write_backend_reg(reset_sbit_cluster_node, 1)
                write_backend_reg(ttc_cyclic_start_node, 1)
                cyclic_running = 1
                t0 = time()
                while (cyclic_running):
                    cyclic_running = read_backend_reg(cyclic_running_node)
                # Stop the cyclic generator
                write_backend_reg(ttc_reset_node, 1)
                #print ("  Time taken for L1A loop with %d L1As and %d BX gap = %.4f us"%(nl1a, l1a_bxgap, (time()-t0)*1e6))
                calpulse_counter = read_backend_reg(calpulse_node)

                cluster_count = 0
                multiple_cluster = 0
                incorrect_cluster = 0
                large_cluster = 0
                for i in range(0, 8):
                    cluster_count_i = read_backend_reg(cluster_count_nodes[i])
                    if i not in [0, 1] and cluster_count_i != 0:
                        multiple_cluster = 1
                        break
                    if i == 1:
                        cluster_count = cluster_count_i
                    sbit_monitor_value = read_backend_reg(
                        sbit_monitor_nodes[i])
                    sbit_cluster_address = sbit_monitor_value & 0x7ff
                    sbit_cluster_size = ((sbit_monitor_value >> 12) & 0x7) + 1
                    if i != 0 and sbit_cluster_address != 0x7ff:
                        multiple_cluster = 1
                        break
                    if i == 0:
                        if sbit_cluster_size > 1:
                            large_cluster = 1
                            break
                        if sbit_cluster_address != 0x7ff and sbit_cluster_address != s_bit_cluster_mapping[
                                vfat][channel]["cluster_address"]:
                            incorrect_cluster = 1
                            break
                if multiple_cluster:
                    print(Colors.YELLOW +
                          "  Multiple clusters detected for CAL_DAC = %d" % c +
                          Colors.ENDC)
                    continue
                if large_cluster:
                    print(Colors.YELLOW +
                          "  Cluster size larger than 1 for CAL_DAC = %d" % c +
                          Colors.ENDC)
                    continue
                if incorrect_cluster:
                    print(Colors.YELLOW +
                          "  Incorrect cluster detected for CAL_DAC = %d" % c +
                          Colors.ENDC)
                    continue

                sbit_data[vfat][channel][charge]["events"] = calpulse_counter
                sbit_data[vfat][channel][charge]["fired"] = cluster_count
            # End of charge loop
            if parallel is None:
                enableVfatchannel(vfat, oh_select, channel, 1,
                                  0)  # mask channel and disable calpulsing
        # End of channel loop
        print("")
    # End of VFAT loop
    if calpulse_only:
        write_backend_reg(
            get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE_CALPULSE_ONLY"), 0)
    else:
        write_backend_reg(get_backend_node("BEFE.GEM.TTC.GENERATOR.ENABLE"), 0)
    print("")

    # Disable channels on VFATs
    for vfat in vfat_list:
        print("Unconfiguring VFAT %d" % (vfat))
        for channel in range(0, 128):
            enableVfatchannel(
                vfat, oh_select, channel, 0,
                0)  # disable calpulsing on all channels for this VFAT
        configureVfat(0, vfat, oh_select, 0)
    write_backend_reg(
        get_backend_node("BEFE.GEM.GEM_SYSTEM.VFAT3.SC_ONLY_MODE"), 0)

    # Writing Results
    for vfat in vfat_list:
        for channel in channel_list:
            for charge in range(0, 256, 1):
                if charge not in sbit_data[vfat][channel]:
                    continue
                file_out.write("%d    %d    %d    %d    %d\n" %
                               (vfat, channel, charge,
                                sbit_data[vfat][channel][charge]["fired"],
                                sbit_data[vfat][channel][charge]["events"]))

    print("")
    file_out.close()