def __init__(self, datadir="data", outlabel="gainMeasurement"):
        self.outpathlabel = os.path.join(datadir, outlabel)

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.cppfr = CPP_FILE_RUNNER()

        #misc variables
        self.gain = 0
        self.shape = 0
        self.base = 0

        #json output, note module version number defined here
        self.jsondict = {'type':'quadFeAsic_gain_fpgadac'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp']  = str(self.write_data.date)
Example #2
0
    def __init__(self,
                 datadir="data",
                 outlabel="simpleMeasurement",
                 wib=0,
                 fembNum=0):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_femb_") + str(fembNum + 4 * wib)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.fembNum = int(fembNum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("FEMB #\t" + str(self.fembNum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 9014
        self.cppfr = CPP_FILE_RUNNER()

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #json output, note module version number defined here
        self.jsondict = {'type': 'fembTest_simple'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
Example #3
0
    def __init__(self,
                 datadir="data",
                 outlabel="simpleMeasurement",
                 asicnum=0,
                 isCold=False):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_asic_") + str(asicnum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.asicnum = int(asicnum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("ASIC socket #\t" + str(self.asicnum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        self.cppfr = CPP_FILE_RUNNER()

        #set appropriate UDP packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000  #should be larger than largest expected packet size

        #set test module status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.isCold = isCold

        #define json output
        self.jsondict = {'type': 'quadAdcTest_simple'}
        #self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
        self.jsondict['asicnum'] = str(self.asicnum)
Example #4
0
    def __init__(self,
                 datadir="data",
                 outlabel="funcgenMeasurement",
                 asicnum=0,
                 doReconfig=True,
                 doLongRamp=False,
                 isExternalClock=True,
                 is1MHzSAMPLERATE=True,
                 isCold=False):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_asic_") + str(asicnum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.asicnum = int(asicnum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("ASIC socket #\t" + str(self.asicnum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        self.cppfr = CPP_FILE_RUNNER()
        self.funcgen = Keysight_33600A("/dev/usbtmc0",
                                       1)  #hardcoded to usbtmc0

        #set appropriate UDP packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000  #should be larger than largest expected packet size

        #set test module status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #assign input to test and config module internal variables
        self.doReconfig = doReconfig
        self.doLongRamp = doLongRamp
        self.isExternalClock = isExternalClock
        self.is1MHzSAMPLERATE = is1MHzSAMPLERATE
        self.isCold = isCold
        self.femb_config.isExternalClock = self.isExternalClock  #False = internal monostable, True = external
        self.femb_config.is1MHzSAMPLERATE = self.is1MHzSAMPLERATE  #False = 1MHz, True = 2MHz
        self.femb_config.COLD = self.isCold
        self.femb_config.enableTest = 1  # 0 = no test input, 1 = enabled

        #define json output
        self.jsondict = {'type': 'quadAdcTest_funcgen'}
        #self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
        self.jsondict['asicnum'] = str(self.asicnum)
        self.jsondict['doreconfig'] = str(self.doReconfig)
        self.jsondict['extclock'] = str(self.isExternalClock)
        self.jsondict['is1MHz'] = str(self.is1MHzSAMPLERATE)
        self.jsondict['iscold'] = str(self.isCold)
Example #5
0
    def __init__(self, datadir="data"):

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000
	
        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.cppfr = CPP_FILE_RUNNER()
Example #6
0
    def __init__(self, datadir="data", outlabel="xtalk", fembNum=0):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_femb_") + str(fembNum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.fembNum = int(fembNum)

        print("FEMB # " + str(self.fembNum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(self.datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000
        self.cppfr = CPP_FILE_RUNNER()

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #misc variables
        self.gain = 0
        self.shape = 0
        self.base = 0
        self.leakage = 0
        self.leakagex10 = 0
        self.buffer = 1
        self.acdc = 0
        self.useInternalPulser = False
        self.useExtAdcClock = False
        self.isRoomTemp = False
        self.isAPA = False
        self.useDefaultGainFactor = False

        #json output, note module version number defined here
        self.jsondict = {'type': 'fembTest_xtalk'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
Example #7
0
    def __init__(self, datadir="data", outlabel="syncData"):
        self.outpathlabel = os.path.join(datadir, outlabel)

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.plotting = plot_functions()
        self.write_data.femb.MAX_PACKET_SIZE = 8000

        self.cppfr = CPP_FILE_RUNNER()

        #json output, note module version number defined here
        self.jsondict = {'type': 'sync_adcs'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
Example #8
0
    def __init__(self, datadir="data", outlabel="baselineTest"):
        
        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #import data analysis and plotting objects
        self.plotting = plot_functions()
        self.analyze = Data_Analysis()
        
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000

        self.cppfr = CPP_FILE_RUNNER()
        
        #json output, note module version number defined here
        self.jsondict = {'type':'baseline_test'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp']  = str(self.write_data.date)     
    def __init__(self):
        #declare basic system parameters
        self.NFEMBS = 4
        self.NASICS = 8
        self.NASICCH = 16

        #declare board specific registers
        self.FEMB_VER = "WIB_SBND"
        self.REG_RESET = 0
        self.REG_ASIC_RESET = 1
        self.REG_ASIC_SPIPROG = 2
        self.REG_SOFT_ADC_RESET = 1

        self.REG_LATCHLOC_3_TO_0 = 4
        self.REG_LATCHLOC_7_TO_4 = 14

        self.REG_FPGA_TP_EN = 16
        self.REG_ASIC_TP_EN = 16
        self.REG_DAC_SELECT = 16
        self.REG_TP = 5

        self.CLK_SELECT = 6
        self.CLK_SELECT2 = 15

        self.REG_SEL_ASIC = 7
        self.REG_SEL_ASIC_LSB = 8

        self.REG_WIB_MODE = 8
        self.REG_ADC_DISABLE = 8

        self.REG_HS_DATA = 9
        self.REG_HS = 17

        self.INT_TP_EN = 18
        self.EXT_TP_EN = 18

        self.REG_SPI_BASE = 0x200
        self.REG_SPI_RDBACK_BASE = 0x250
        
        self.REG_TEST_PAT = 3
        self.REG_TEST_PAT_DATA = 0x01230000

        #internal variables
        self.fembNum = 0
        self.wibNum = 0
        self.useExtAdcClock = True
        self.isRoomTemp = False
        self.doReSync = True
        self.spiStatus = 0x0
        self.syncStatus = 0x0
        self.CLKSELECT_val_RT = 0xFF
        self.CLKSELECT2_val_RT = 0xFF
        self.CLKSELECT_val_CT = 0xEF
        self.CLKSELECT2_val_CT = 0xEF
        self.REG_LATCHLOC_3_TO_0_val = 0x04040404
        self.REG_LATCHLOC_7_TO_4_val = 0x04040404
        self.fe_regs = [0x00000000]*(16+2)*8*8
        self.fe_REGS = [0x00000000]*(8+1)*4
        self.useLArIATmap = False #True

        #COTS shifts
        self.fe1_sft_RT = 0x00000000
        self.fe2_sft_RT = 0x00000000
        self.fe3_sft_RT = 0x00000000
        self.fe4_sft_RT = 0x00000000
        self.fe5_sft_RT = 0x00000000
        self.fe6_sft_RT = 0x00000000
        self.fe7_sft_RT = 0x00000000
        self.fe8_sft_RT = 0x00000000

        self.fe1_sft_CT = 0x00000000
        self.fe2_sft_CT = 0x00000000
        self.fe3_sft_CT = 0x00000000
        self.fe4_sft_CT = 0x00000000
        self.fe5_sft_CT = 0x00000000
        self.fe6_sft_CT = 0x00000000
        self.fe7_sft_CT = 0x00000000
        self.fe8_sft_CT = 0x00000000
            
        #COTS phases
        self.fe1_pha_RT = 0x00000000
        self.fe2_pha_RT = 0x00000000
        self.fe3_pha_RT = 0x00000000
        self.fe4_pha_RT = 0x00000000
        self.fe5_pha_RT = 0x00000000
        self.fe6_pha_RT = 0x00000000
        self.fe7_pha_RT = 0x00000000
        self.fe8_pha_RT = 0x00000000

        self.fe1_pha_CT = 0x00000000
        self.fe2_pha_CT = 0x00000000
        self.fe3_pha_CT = 0x00000000
        self.fe4_pha_CT = 0x00000000
        self.fe5_pha_CT = 0x00000000
        self.fe6_pha_CT = 0x00000000
        self.fe7_pha_CT = 0x00000000
        self.fe8_pha_CT = 0x00000000
        
        #initialize FEMB UDP object
        self.femb = FEMB_UDP()
        self.femb.UDP_PORT_WREG = 32000 #WIB PORTS
        self.femb.UDP_PORT_RREG = 32001
        self.femb.UDP_PORT_RREGRESP = 32002
        self.femb.doReadBack = False #WIB register interface is unreliable

        #ASIC config variables
        self.feasicLeakage = 0 #0 = 500pA, 1 = 100pA
        self.feasicLeakagex10 = 0 #0 = pA, 1 = pA*10
        self.feasicAcdc = 0 #AC = 0, DC = 1
        self.feasicBaseline = 0 #0 = 900mV, 1 = 200mV        
        self.feasicEnableTestInput = 0 #0 = disabled, 1 = enabled
        self.feasicGain = 2 #4.7,7.8,14,25
        self.feasicShape = 1 #0.5,1,2,3
        self.feasicBuf = 1 #0 = OFF, 1 = ON

        #Read in LArIAT mapping if desired

        if self.useLArIATmap:
            self.cppfr = CPP_FILE_RUNNER()            
            with open(self.cppfr.filename('configuration/configs/LArIAT_pin_mapping.map'), "rb") as fp:
                self.lariatMap = pickle.load(fp)
                
            #APA Mapping
            va = self.lariatMap
            va_femb = []
            for vb in va:
                if int(vb[9]) in (0,1,2,3,4) :
                    va_femb.append(vb)
            apa_femb_loc = []
            for chn in range(128):
                for vb in va_femb:
                    if int(vb[8]) == chn:
                        if (vb[1].find("Co")) >= 0 :#collection wire
                            chninfo = [ "X" + vb[0], vb[8], int(vb[6]), int(vb[7]), int(vb[9]), int(vb[10])]
                        elif (vb[1].find("In")) >= 0 : #induction wire
                            chninfo = [ "U" + vb[0], vb[8], int(vb[6]), int(vb[7]), int(vb[9]), int(vb[10])]
                        apa_femb_loc.append(chninfo)
            for chn in range(128):
                fl_w = True
                fl_i = 0
                for tmp in apa_femb_loc:
                    if int(tmp[1]) == chn:
                        fl_w = False
                        break
                if (fl_w):
                    chninfo = [ "V" + format(fl_i, "03d"), format(chn, "03d"), chn//16 , format(chn%15, "02d"), apa_femb_loc[0][4], apa_femb_loc[0][5]]
                    apa_femb_loc.append(chninfo)
                    fl_i = fl_i + 1

            self.All_sort = []
            self.X_sort = []
            self.V_sort = []
            self.U_sort = []
            for i in range(128):
                for chn in apa_femb_loc:
                    if int(chn[1][0:3]) == i :
                        self.All_sort.append(chn)
    
                    for chn in apa_femb_loc:
                        if chn[0][0] == "X" and int(chn[0][1:3]) == i :
                            self.X_sort.append(chn)
                    for chn in apa_femb_loc:
                        if chn[0][0] == "V" and int(chn[0][1:3]) == i :
                            self.V_sort.append(chn)
                    for chn in apa_femb_loc:
                        if chn[0][0] == "U" and int(chn[0][1:3]) == i :
                            self.U_sort.append(chn)

            self.WireDict = {}
            for line in self.All_sort:
                key = "wib{:d}_femb{:d}_chip{:d}_chan{:02d}".format(line[5],line[4],line[2],line[3])
                self.WireDict[key] = line[0]
Example #10
0
class QUADADC_TEST_SIMPLE(object):
    def __init__(self,
                 datadir="data",
                 outlabel="simpleMeasurement",
                 asicnum=0,
                 isCold=False):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_asic_") + str(asicnum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.asicnum = int(asicnum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("ASIC socket #\t" + str(self.asicnum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        self.cppfr = CPP_FILE_RUNNER()

        #set appropriate UDP packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000  #should be larger than largest expected packet size

        #set test module status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.isCold = isCold

        #define json output
        self.jsondict = {'type': 'quadAdcTest_simple'}
        #self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
        self.jsondict['asicnum'] = str(self.asicnum)

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("SIMPLE MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        #make sure output directory exists (should catch permissions issues etc)
        isDir = self.write_data.assure_filedir()
        if isDir == None:
            print("Error running test - Output data directory note created.")
            return

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(
            self.femb_config.REG_FIRMWARE_VERSION)
        if (regVal == None):
            print("Error running test - register interface is not working.")
            print(" Turn on or debug UDP readout.")
            return
        if (regVal < 0):
            print("Error running test - register interface is not working.")
            print(" Turn on or debug UDP readout.")
            return
        print("Read register 6, value = " + str(hex(regVal)))

        #check for any problems in input variables
        #check that input ASIC # is correct
        if self.asicnum == None:
            print(
                "Error running test - Invalid ASIC socket # specified, ending test"
            )
            return
        if (self.asicnum < 0) or (self.asicnum > self.femb_config.NASICS):
            print(
                "Error running test - Invalid ASIC socket # specified, ending test"
            )
            return

        #initialize readout to known working state
        #initialization may identify problem that cancels test
        print("Initializing board")
        initStatus = self.femb_config.initBoard()
        if initStatus == False:
            print(
                "Error running test - Could not initialize board, ending test")
            return
        initStatus = self.femb_config.initAsic(self.asicnum)
        if initStatus == False:
            print(
                "Error running test - Could not initialize ASIC, ending test")
            return

        #firmware version check should be done in initialize, otherwise do here
        #if self.femb_config.checkFirmwareVersion() == False:
        #    print('Error running doFembTest - Invalid firmware and/or register read error')
        #    return

        #check if data streaming is working, assume it's ON after board + ASIC initialize
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running test - board is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return
        if len(testData) == 0:
            print("Error running test - board is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists(
                'test_measurements/quadAdcTester/code/parseBinaryFile'):
            print(
                'Error running test - parseBinaryFile executable not found, run setup.sh'
            )
            return
        if not self.cppfr.exists(
                'test_measurements/quadAdcTester/code/processNtuple_simpleMeasurement'
        ):
            print(
                'Error running test - processNtuple_simpleMeasurement executable not found, run setup.sh'
            )
            return

        #Setup is ok
        print("SIMPLE MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print(
                "Error running test - Please run check_setup method before trying to take data"
            )
            return
        if self.status_record_data == 1:
            print(
                "Error running test - Data already recorded. Reset/restat GUI to begin a new measurement"
            )
            return

        #MEASUREMENT SECTION
        print("SIMPLE MEASUREMENT - RECORDING DATA")

        #wait to make sure HS link is back on after check_setup function
        sleep(1.)

        #setup output file and record data
        self.write_data.filename = self.outlabel + ".bin"
        print("Recording " + self.write_data.filename)

        isOpen = self.write_data.open_file()
        if isOpen == 0:
            print(
                "Error running test - Could not open output data file for writing, ending test"
            )

        #record data
        self.write_data.numpacketsrecord = 10
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        #loop over each ASIC, record some data
        subrun = 0
        asic = self.asicnum
        asicCh = 0
        self.femb_config.selectAsic(asic)
        self.write_data.record_data(subrun, asic, asicCh)
        self.write_data.close_file()

        #Power off ASIC
        #self.femb_config.turnOffAsics()

        print("SIMPLE MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Error running test - Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Error running test - Analysis already complete")
            return

        #ANALYSIS SECTION
        print("SIMPLE MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/quadAdcTester/code/parseBinaryFile",
                       [self.write_data.data_file_path])

        #check for parsed file here
        if os.path.isfile("output_parseBinaryFile.root") == False:
            print("Error running test - parsed data file not found.")
            return

        #run analysis program
        parseBinaryFile = "output_parseBinaryFile.root"
        self.cppfr.run(
            "test_measurements/quadAdcTester/code/processNtuple_simpleMeasurement",
            [parseBinaryFile])

        #check for online analysis result files here
        if os.path.isfile(
                "output_processNtuple_simpleMeasurement.root") == False:
            print("Error running test - parsed data file not found.")
            return

        #update output file names
        parseBinaryFile = self.outpathlabel + "-parseBinaryFile.root"
        call(["mv", "output_parseBinaryFile.root", parseBinaryFile])

        processNtupleFile = self.outpathlabel + "-processNtupleFile.root"
        call([
            "mv", "output_processNtuple_simpleMeasurement.root",
            processNtupleFile
        ])

        summaryPlot = self.outpathlabel + "-summaryPlot.png"
        call(["mv", "summaryPlot_simpleMeasurement.png", summaryPlot])

        print("SIMPLE MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA" +
              "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        #NOTE: GENERALLY ALLOW ARCHIVE PROCESS TO RUN EVEN IF OTHER STEPS FAIL
        #if self.status_check_setup == 0 :
        #     print("Check setup status is 0, not archiving data")
        #     return
        #if self.status_do_analysis == 0:
        #    print("Please analyze data before archiving results")
        #    return
        if self.status_archive_results == 1:
            print("Error running test - Results already archived")
            return
        #ARCHIVE SECTION
        print("SIMPLE MEASUREMENT - ARCHIVE")

        #add summary variables to output
        self.jsondict['filedir'] = str(self.write_data.filedir)
        self.jsondict['status_check_setup'] = str(self.status_check_setup)
        self.jsondict['status_record_data'] = str(self.status_record_data)
        self.jsondict['status_do_analysis'] = str(self.status_do_analysis)
        self.jsondict['status_archive_results'] = str(1)

        #dump results into json
        jsonFile = self.outpathlabel + "-results.json"
        with open(jsonFile, 'w') as outfile:
            json.dump(self.jsondict, outfile, indent=4)

        print("SIMPLE MEASUREMENT - DONE ARCHIVING" + "\n")
        self.status_archive_results = 1
Example #11
0
class FEMB_TEST_SIMPLE(object):
    def __init__(self,
                 datadir="data",
                 outlabel="simpleMeasurement",
                 wib=0,
                 fembNum=0):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_femb_") + str(fembNum + 4 * wib)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.fembNum = int(fembNum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("FEMB #\t" + str(self.fembNum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 9014
        self.cppfr = CPP_FILE_RUNNER()

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #json output, note module version number defined here
        self.jsondict = {'type': 'fembTest_simple'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("SIMPLE MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        #make sure output directory exists
        self.write_data.assure_filedir()

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(6)
        if (regVal == None):
            print(
                "Error running test - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")
            return
        if (regVal < 0):
            print(
                "Error running test - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")
            return
        print("Read register 6, value = " + str(hex(regVal)))

        #check that femb number is valid
        if (int(self.fembNum) < 0) or (int(self.fembNum) >=
                                       self.femb_config.NFEMBS):
            print("Error running doFembTest - Invalid FEMB # specified.")
            return

        #DO NOT CONFIGURE, except to enable streaming
        self.femb_config.wib_reg_enable()

        self.femb_config.femb.write_reg(20, 3)
        self.femb_config.femb.write_reg(20, 3)
        time.sleep(0.001)
        self.femb_config.femb.write_reg(20, 0)
        self.femb_config.femb.write_reg(20, 0)
        time.sleep(0.001)

        # start streaming data from ASIC 0 in initialization
        self.femb_config.femb.write_reg(7, 0x80000000)
        self.femb_config.femb.write_reg(7, 0x80000000)
        femb_asic = 0 & 0x0F
        wib_asic = (((self.fembNum << 16) & 0x000F0000) +
                    ((femb_asic << 8) & 0xFF00))
        self.femb_config.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb_config.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb_config.femb.write_reg(7, wib_asic)
        self.femb_config.femb.write_reg(7, wib_asic)

        self.femb_config.selectFemb(self.fembNum)

        #Enable Streaming
        self.femb_config.femb.write_reg(9, 9)
        self.femb_config.femb.write_reg(9, 9)
        time.sleep(0.1)

        #test firmware versions
        if self.femb_config.checkFirmwareVersion() == False:
            print(
                'Error running doFembTest - Invalid firmware and/or register read error'
            )
            return

        if self.femb_config.syncStatus != 0:
            print('Error running doFembTest - ADC SYNC failed')
            return

        if self.femb_config.spiStatus != 0:
            print('Error running doFembTest - ADC SPI failed')
            return

        #check if data streaming is working
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return
        if len(testData) == 0:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists(
                'test_measurements/fembTest/code/parseBinaryFile'):
            print('parseBinaryFile not found, run setup.sh')
            return

        print("SIMPLE MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print("Please run check_setup method before trying to take data")
            return
        if self.status_record_data == 1:
            print(
                "Data already recorded. Reset/restat GUI to begin a new measurement"
            )
            return

        #MEASUREMENT SECTION
        print("SIMPLE MEASUREMENT - RECORDING DATA")

        #wait to make sure HS link is back on after check_setup
        sleep(5)

        self.femb_config.printParameters()

        #setup output file and record data
        self.write_data.filename = self.outlabel + ".bin"
        print("Recording " + self.write_data.filename)

        isOpen = self.write_data.open_file()
        if isOpen == 0:
            print(
                "Error running doFembTest - Could not open output data file for writing, ending test"
            )
        subrun = 0

        #record data
        self.write_data.numpacketsrecord = 100
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        asicCh = 0
        for asic in range(0, 8, 1):
            self.femb_config.selectChannel(asic, asicCh)
            self.write_data.record_data(subrun, asic, asicCh)
        self.write_data.close_file()

        print("SIMPLE MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Analysis already complete")
            return
        #ANALYSIS SECTION

        print("SIMPLE MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/fembTest/code/parseBinaryFile",
                       [self.write_data.data_file_path])

        #run analysis program
        parseBinaryFile = self.outpathlabel + "-parseBinaryFile.root"
        call(["mv", "output_parseBinaryFile.root", parseBinaryFile])
        self.cppfr.run(
            "test_measurements/fembTest/code/processNtuple_simpleMeasurement",
            [parseBinaryFile])

        processNtupleFile = self.outpathlabel + "-processNtupleFile.root"
        call([
            "mv", "output_processNtuple_simpleMeasurement.root",
            processNtupleFile
        ])

        summaryPlot = self.outpathlabel + "-summaryPlot.png"
        call(["mv", "summaryPlot_simpleMeasurement.png", summaryPlot])

        print("SIMPLE MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA" +
              "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        #if self.status_check_setup == 0 :
        #     print("Check setup status is 0, not archiving data")
        #     return
        #if self.status_do_analysis == 0:
        #    print("Please analyze data before archiving results")
        #    return
        if self.status_archive_results == 1:
            print("Results already archived")
            return
        #ARCHIVE SECTION
        print("SIMPLE MEASUREMENT - ARCHIVE")

        #add summary variables to output
        self.jsondict['femb'] = self.fembNum
        self.jsondict['filedir'] = str(self.write_data.filedir)
        self.jsondict['status_check_setup'] = str(self.status_check_setup)
        self.jsondict['status_record_data'] = str(self.status_record_data)
        self.jsondict['status_do_analysis'] = str(self.status_do_analysis)
        self.jsondict['status_archive_results'] = str(1)
        self.jsondict['syncStatus'] = str(self.femb_config.syncStatus)

        #dump results into json
        jsonFile = self.outpathlabel + "-results.json"
        with open(jsonFile, 'w') as outfile:
            json.dump(self.jsondict, outfile, indent=4)

        print("SIMPLE MEASUREMENT - DONE ARCHIVING" + "\n")
        self.status_archive_results = 1
Example #12
0
class FEMB_TEST_SIMPLE(object):

    def __init__(self, datadir="data"):

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000
	
        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.cppfr = CPP_FILE_RUNNER()

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("SIMPLE MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        self.write_data.assure_filedir()

        #create data-taking directory
        #print("doFembTest - creating data-taking directory : " + str( self.write_data.filedir ) )
        #os.makedirs( str( self.write_data.filedir ) )
        #if os.path.isdir( str( self.write_data.filedir ) ) == False:
        #    print("Error creating data-taking directory.")
        #    return

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(6)
        if (regVal == None) or (regVal == -1):
            print("Error running doFembTest - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")       
            return
        print("Read register 6, value = " + str( hex( regVal ) ) )

        #initialize FEMB to known state
        print("Initializing board")
        self.femb_config.initBoard()

        #check if data streaming is working
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return
        if len(testData) == 0:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists('test_measurements/example_femb_test/parseBinaryFile'):    
            print('parseBinaryFile not found, run setup.sh')
            #sys.exit(0)
            return

        print("SIMPLE MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print("Please run check_setup method before trying to take data")
            return
        if self.status_record_data == 1:
            print("Data already recorded. Reset/restat GUI to begin a new measurement")
            return

        #MEASUREMENT SECTION
        print("SIMPLE MEASUREMENT - RECORDING DATA")

        #initialize FEMB configuration to known state

        self.femb_config.feasicGain = 1 #4.7,7.8,14,25
        self.femb_config.feasicShape = 2 #0.5,1,2,3
        self.femb_config.feasicBaseline = 1 #0 = 200mV, 1 = 900mV
        self.femb_config.feasicLeakage = 0 #0 = 500pA, 1 = 100pA
        self.femb_config.feasicLeakagex10 = 1 #0 = x1, 1 = x10
        self.femb_config.feasicBuf = 1 #0 = OFF, 1 = ON
        self.femb_config.feasicAcdc = 0 #AC = 0, DC = 1
        self.femb_config.feasicEnableTestInput = 1 #OFF = 0, ON = 1
        self.femb_config.configFeAsic()

        #disable pulser
        self.femb_config.setDacPulser(0,0x0)
        self.femb_config.setFpgaPulser(0,0x0)
        self.femb_config.setExternalFpgaPulser(0,0x0)
        self.femb_config.setInternalPulser(1,0x5)

        #wait to make sure HS link is back on
        #sleep(0.5)

        #set output file
        self.write_data.filename = "rawdata_simpleMeasurement_" + str(self.write_data.date) + ".bin"
        print("Recording " + self.write_data.filename )
        self.write_data.numpacketsrecord = 10
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        #setup output file and record data
        isOpen = self.write_data.open_file()
        if isOpen == 0 :
            print( "Error running doFembTest - Could not open output data file for writing, ending test" )
        subrun = 0

        asicCh = 0
        for asic in range(0,4,1):
          for asicCh in range(0,16,1):
            self.femb_config.selectChannel(asic,asicCh)
            self.write_data.record_data(subrun, asic, asicCh)
        self.write_data.close_file()

        #turn off ASICs
        self.femb_config.turnOffAsics()

        print("SIMPLE MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Analysis already complete")
            return
        #ANALYSIS SECTION
        print("SIMPLE MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/feAsicTest/parseBinaryFile", [self.write_data.data_file_path])

        #run analysis program
        newName = "output_parseBinaryFile_" + self.write_data.filename + ".root"
        newPath = os.path.join(self.write_data.filedir, newName)
        call(["mv", "output_parseBinaryFile.root" , newPath])
        self.cppfr.run("test_measurements/feAsicTest/processNtuple_simpleMeasurement",  [newPath])

        #move result to data directory
        newName = "output_processNtuple_simpleMeasurement_" + self.write_data.filename + ".root"
        newPath = os.path.join(self.write_data.filedir, newName)
        call(["mv", "output_processNtuple_simpleMeasurement.root" , newPath ])
        newName = "summaryPlot_" + self.write_data.filename + ".png"
        newPath = os.path.join(self.write_data.filedir, newName)
        call(["mv", "summaryPlot_simpleMeasurement.png" , newPath])

        #summary plot
        #print("SIMPLE MEASUREMENT - DISPLAYING SUMMARY PLOT, CLOSE PLOT TO CONTINUE")
        call(["display",str( newPath ) ])

        print("SIMPLE MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA" + "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        if self.status_do_analysis == 0:
            print("Please analyze data before archiving results")
            return
        if self.status_archive_results == 1:
            print("Results already archived")
            return
        #ARCHIVE SECTION
        print("SIMPLE MEASUREMENT - STORE RESULTS IN DATABASE")
        #placeholder
        print("SIMPLE MEASUREMENT - DONE STORING RESULTS IN DATABASE" + "\n")
        self.status_archive_results = 1
class FEMB_TEST_GAIN_FPGADAC(object):

    def __init__(self, datadir="data", outlabel="gainMeasurement"):
        self.outpathlabel = os.path.join(datadir, outlabel)

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.cppfr = CPP_FILE_RUNNER()

        #misc variables
        self.gain = 0
        self.shape = 0
        self.base = 0

        #json output, note module version number defined here
        self.jsondict = {'type':'quadFeAsic_gain_fpgadac'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp']  = str(self.write_data.date)

    def reset(self):
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("GAIN MEASUREMENT FPGA DAC - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        self.write_data.assure_filedir()

        #check if register interface is working
        print("Checking register interface")
        regVal = self.write_data.femb.read_reg(5)
        if (regVal == None) or (regVal == -1):
            print("Error running doFembTest - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")       
            return
        print("Read register 5, value = " + str( hex( regVal ) ) )

        #initialize FEMB to known state
        print("Initializing board")
        self.femb_config.initBoard()

        #check if data streaming is working
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return
        if len(testData) == 0:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists('test_measurements/example_femb_test/parseBinaryFile'):    
            print('parseBinaryFile not found, run setup.sh')
            #sys.exit(0)
            return

        print("GAIN MEASUREMENT FPGA DAC - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print("Please run check_setup method before trying to take data")
            return
        if self.status_record_data == 1:
            print("Data already recorded. Reset/restat GUI to begin a new measurement")
            return
        #MEASUREMENT SECTION
        print("GAIN MEASUREMENT FPGA DAC - RECORDING DATA")

        #initialize FEMB configuration to known state
        print("FE ASIC Settings: Gain " + str(self.gain) + ", Shaping Time " + str(self.shape) + ", Baseline " + str(self.base) )
        self.femb_config.feasicGain = self.gain
        self.femb_config.feasicShape = self.shape
        self.femb_config.feasicBaseline = self.base
        self.femb_config.configFeAsic()

        #disable pulser
        self.femb_config.setInternalPulser(0,0x0)
        self.femb_config.setDacPulser(0,0x0)
        self.femb_config.setFpgaPulser(0,0x0)

        #setup output file and record data
        self.write_data.filename = self.outpathlabel+".bin"

        print("Recording " + self.write_data.filename )
        self.write_data.numpacketsrecord = 50
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0
        self.write_data.open_file()

        #take initial noise data run
        subrun = 0
        for asic in range(0,4,1):
            self.femb_config.turnOffAsics()
            self.femb_config.turnOnAsic(asic)
            time.sleep(5) # wait extra for power to settle 
            for asicCh in range(0,16,1):
                self.femb_config.selectChannel(asic,asicCh)
                self.write_data.record_data(subrun, asic, asicCh)
            
        #turn ASICs back on, start pulser section
        self.femb_config.feasicEnableTestInput = 1
        self.femb_config.turnOnAsics()
        subrun = 1
        #loop over pulser configurations, each configuration is it's own subrun
        #for p in range(1,2,1):
        for p in range(1,0x3F,1):
            pVal = int(p)
            self.femb_config.setFpgaPulser(1,pVal)
            print("Pulse amplitude " + str(pVal) )

            #loop over channels
            for asic in range(0,4,1):
                for asicCh in range(0,16,1):
                    self.femb_config.selectChannel(asic,asicCh)
                    self.write_data.record_data(subrun, asic, asicCh)

            #increment subrun, important
            subrun = subrun + 1

        #close file
        self.write_data.close_file()

        #turn off pulser
        self.femb_config.setFpgaPulser(0,0)

        #turn off ASICs
        self.femb_config.turnOffAsics()

        print("GAIN MEASUREMENT FPGA DAC - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Analysis already complete")
            return
        #ANALYSIS SECTION
        print("GAIN MEASUREMENT FPGA DAC - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/feAsicTest/parseBinaryFile", [self.write_data.data_file_path])

        #run analysis program
        parseBinaryFile = self.outpathlabel + "-parseBinaryFile.root"
        call(["mv", "output_parseBinaryFile.root" , parseBinaryFile])
        self.cppfr.run("test_measurements/feAsicTest/processNtuple_gainMeasurement_fpgadac",  [parseBinaryFile])

        processNtupleFile = self.outpathlabel + "-processNtupleFile.root"
        call(["mv", "output_processNtuple_gainMeasurement_fpgadac.root" , processNtupleFile])

        summaryPlot = self.outpathlabel + "-summaryPlot.png"
        call(["mv", "summaryPlot_gainMeasurement_fpgadac.png" , summaryPlot])

        resultsFile = self.outpathlabel + "-results.list"
        call(["mv", "output_processNtuple_gainMeasurement_fpgadac.list" , resultsFile])

        #summary plot
        #print("GAIN MEASUREMENT - DISPLAYING SUMMARY PLOT, CLOSE PLOT TO CONTINUE")
        #call(["display", newPath])

        print("GAIN MEASUREMENT FPGA DAC - DONE ANALYZING AND SUMMARIZING DATA" + "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        #if self.status_do_analysis == 0:
        #    print("Please analyze data before archiving results")
        #    return
        #if self.status_archive_results == 1:
        #    print("Results already archived")
        #    return
        #ARCHIVE SECTION
        print("GAIN MEASUREMENT FPGA DAC - ARCHIVE")

        #add summary variables to output
        self.jsondict['status_check_setup'] = str( self.status_check_setup )
        self.jsondict['status_record_data'] = str( self.status_record_data )
        self.jsondict['status_do_analysis'] = str( self.status_do_analysis )
        self.jsondict['filedir'] = str( self.write_data.filedir )
        self.jsondict['config_gain'] = str( self.gain )
        self.jsondict['config_shape'] = str( self.shape )
        self.jsondict['config_base'] = str( self.base )

        if self.status_do_analysis == 1:
          #parse the output results, kind of messy
          listFile = self.outpathlabel + "-results.list"

          lines = []
          with open( listFile ) as infile:
            for line in infile:
                line = line.strip('\n')
                line = line.split(',') #measurements separated by commas
                parseline = {}
                for n in range(0,len(line),1):
                    word = line[n].split(' ')
                    if( len(word) != 2 ):
                        continue
                    parseline[ str(word[0]) ] = str(word[1])
                lines.append(parseline)
            self.jsondict['results'] = lines

        #dump results into json
        jsonFile = self.outpathlabel + "-results.json"
        with open( jsonFile , 'w') as outfile:
            json.dump( self.jsondict, outfile, indent=4)

        #get required results from dict to propagate to GUI
        """
        asicStatus = []
        if "results" in self.jsondict:
          results = self.jsondict["results"]
          for d in results:
            if "asic" in d:
              asicNum = d["asic"]
              fail = d["fail"]
              asicStatus.append( [asicNum,fail] )
        """
        print("GAIN MEASUREMENT - DONE ARCHIVING" + "\n")
        self.status_archive_results = 1
class QUADADC_TEST_FUNCGEN(object):
    def __init__(self,
                 datadir="data",
                 outlabel="funcgenMeasurement",
                 asicnum=0,
                 doReconfig=True,
                 isExternalClock=True,
                 is1MHzSAMPLERATE=True,
                 isCold=False):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_asic_") + str(asicnum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.asicnum = int(asicnum)

        print("Test type\t" + str(self.outlabel))
        print("Data path\t" + str(datadir))
        print("ASIC socket #\t" + str(self.asicnum))

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(datadir)
        self.cppfr = CPP_FILE_RUNNER()
        self.funcgen = Keysight_33600A("/dev/usbtmc0",
                                       1)  #hardcoded to usbtmc0

        #set appropriate UDP packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000  #should be larger than largest expected packet size

        #set test module status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #assign input to test and config module internal variables
        self.doReconfig = doReconfig
        self.isExternalClock = isExternalClock
        self.is1MHzSAMPLERATE = is1MHzSAMPLERATE
        self.isCold = isCold
        self.femb_config.isExternalClock = self.isExternalClock  #False = internal monostable, True = external
        self.femb_config.is1MHzSAMPLERATE = self.is1MHzSAMPLERATE  #False = 1MHz, True = 2MHz
        self.femb_config.COLD = self.isCold

        #define json output
        self.jsondict = {'type': 'quadAdcTest_funcgen'}
        #self.jsondict['version'] = '1.0'
        self.jsondict['timestamp'] = str(self.write_data.date)
        self.jsondict['asicnum'] = str(self.asicnum)
        self.jsondict['doreconfig'] = str(self.doReconfig)
        self.jsondict['extclock'] = str(self.isExternalClock)
        self.jsondict['is1MHz'] = str(self.is1MHzSAMPLERATE)
        self.jsondict['iscold'] = str(self.isCold)

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("FUNCTION GENERATOR MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        #make sure output directory exists (should catch permissions issues etc)
        isDir = self.write_data.assure_filedir()
        if isDir == None:
            print("Error running test - Output data directory note created.")
            return

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(
            self.femb_config.REG_FIRMWARE_VERSION)
        if (regVal == None):
            print("Error running test - register interface is not working.")
            print(" Turn on or debug UDP readout.")
            return
        if (regVal < 0):
            print("Error running test - register interface is not working.")
            print(" Turn on or debug UDP readout.")
            return
        print("Read register 6, value = " + str(hex(regVal)))

        #check for any problems in input variables
        #check that input ASIC # is correct
        if self.asicnum == None:
            print(
                "Error running test - Invalid ASIC socket # specified, ending test"
            )
            return
        if (self.asicnum < 0) or (self.asicnum > self.femb_config.NASICS):
            print(
                "Error running test - Invalid ASIC socket # specified, ending test"
            )
            return

        #initialize readout to known working state
        #initialization may identify problem that cancels test
        if self.doReconfig == True:
            print("Initializing board")
            initStatus = self.femb_config.initBoard()
            if initStatus == False:
                print(
                    "Error running test - Could not initialize board, ending test"
                )
                return
            initStatus = self.femb_config.initAsic(self.asicnum)
            if initStatus == False:
                print(
                    "Error running test - Could not initialize ASIC, ending test"
                )
                return

        #firmware version check should be done in initialize, otherwise do here
        #if self.femb_config.checkFirmwareVersion() == False:
        #    print('Error running doFembTest - Invalid firmware and/or register read error')
        #    return

        #check if data streaming is working, assume it's ON after board + ASIC initialize
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running test - board is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return
        if len(testData) == 0:
            print("Error running test - board is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists(
                'test_measurements/quadAdcTester/code/parseBinaryFile'):
            print(
                'Error running test - parseBinaryFile executable not found, run setup.sh'
            )
            return
        #if not self.cppfr.exists('test_measurements/quadAdcTester/code/processNtuple_funcgenMeasurement'):
        #    print('Error running test - processNtuple_funcgenMeasurement executable not found, run setup.sh')
        #    return

        #Setup is ok
        print("FUNCTION GENERATOR MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print(
                "Error running test - Please run check_setup method before trying to take data"
            )
            return
        if self.status_record_data == 1:
            print(
                "Error running test - Data already recorded. Reset/restat GUI to begin a new measurement"
            )
            return

        #MEASUREMENT SECTION
        print("FUNCTION GENERATOR MEASUREMENT - RECORDING DATA")

        #wait to make sure HS link is back on after check_setup function
        sleep(1.)

        #enable external signal input
        self.femb_config.setFPGADac(0, 1, 0, 0)  # write regs 4 and 5

        #print config parameters just before data taking
        self.femb_config.printParameters()

        #data recording parameters
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        #setup output file and record data
        self.write_data.filename = self.outlabel + ".bin"
        print("Recording " + self.write_data.filename)
        isOpen = self.write_data.open_file()
        if isOpen == 0:
            print(
                "Error running test - Could not open output data file for writing, ending test"
            )

        #speicify ASIC
        asic = self.asicnum
        asicCh = 0
        self.femb_config.selectAsic(asic)

        #initialize function generator parameters
        xLow = -0.3
        xHigh = 1.7
        offsetV = (xLow + xHigh) * 0.5
        amplitudeV = (xHigh - xLow) * 0.5
        settlingTime = 0.1

        #take a bunch of function generator data in sequence and stick it all in the same output file

        #long ramp
        subrun = 0
        freq = 4
        self.funcgen.startRamp(freq, xLow, xHigh)
        sleep(settlingTime)
        self.write_data.numpacketsrecord = 20000  #long
        self.write_data.record_data(subrun, asic, asicCh)

        #short ramp
        subrun = subrun + 1
        freq = 734
        self.funcgen.startRamp(freq, xLow, xHigh)
        sleep(settlingTime)
        self.write_data.numpacketsrecord = 1600
        self.write_data.record_data(subrun, asic, asicCh)

        #DC [0.2,0.5,1.,1.6]
        for dc in [0.2, 0.5, 1., 1.6]:
            subrun = subrun + 1
            self.funcgen.startDC(dc)
            sleep(settlingTime)
            self.write_data.numpacketsrecord = 160
            self.write_data.record_data(subrun, asic, asicCh)

        #SINE [6.2365e4,4.83587e5,9.515125e5]
        for freq in [6.2365e4, 4.83587e5, 9.515125e5]:
            subrun = subrun + 1
            self.funcgen.startSin(freq, amplitudeV, offsetV)
            sleep(settlingTime)
            self.write_data.numpacketsrecord = 1600
            self.write_data.record_data(subrun, asic, asicCh)

        #done taking data
        self.write_data.close_file()

        #Power off ASIC
        #self.femb_config.turnOffAsics()

        #disable external signal input
        self.femb_config.setFPGADac(0, 0, 0, 0)  # write regs 4 and 5

        #turn off function generator
        sleep(1)
        self.funcgen.stop()
        sleep(1)

        print("FUNCTION GENERATOR MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Error running test - Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Error running test - Analysis already complete")
            return

        #ANALYSIS SECTION
        print(
            "FUNCTION GENERATOR MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/quadAdcTester/code/parseBinaryFile",
                       [self.write_data.data_file_path])

        #check for parsed file here
        if os.path.isfile("output_parseBinaryFile.root") == False:
            print("Error running test - parsed data file not found.")
            return

        #run analysis program
        parseBinaryFile = "output_parseBinaryFile.root"
        #self.cppfr.run("test_measurements/quadAdcTester/code/processNtuple_funcgenMeasurement",  [parseBinaryFile])

        #check for online analysis result files here
        #if os.path.isfile( "output_processNtuple_funcgenMeasurement.root" ) == False:
        #    print("Error running test - parsed data file not found.")
        #    return

        #update output file names
        parseBinaryFile = self.outpathlabel + "-parseBinaryFile.root"
        call(["mv", "output_parseBinaryFile.root", parseBinaryFile])

        #processNtupleFile = self.outpathlabel + "-processNtupleFile.root"
        #call(["mv", "output_processNtuple_funcgenMeasurement.root" , processNtupleFile])

        #summaryPlot = self.outpathlabel + "-summaryPlot.png"
        #call(["mv", "summaryPlot_funcgenMeasurement.png" , summaryPlot])

        print(
            "FUNCTION GENERATOR MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA"
            + "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        #NOTE: GENERALLY ALLOW ARCHIVE PROCESS TO RUN EVEN IF OTHER STEPS FAIL
        #if self.status_check_setup == 0 :
        #     print("Check setup status is 0, not archiving data")
        #     return
        #if self.status_do_analysis == 0:
        #    print("Please analyze data before archiving results")
        #    return
        if self.status_archive_results == 1:
            print("Error running test - Results already archived")
            return
        #ARCHIVE SECTION
        print("FUNCTION GENERATOR MEASUREMENT - ARCHIVE")

        #add summary variables to output
        self.jsondict['filedir'] = str(self.write_data.filedir)
        self.jsondict['status_check_setup'] = str(self.status_check_setup)
        self.jsondict['status_record_data'] = str(self.status_record_data)
        self.jsondict['status_do_analysis'] = str(self.status_do_analysis)
        self.jsondict['status_archive_results'] = str(1)

        #dump results into json
        jsonFile = self.outpathlabel + "-results.json"
        with open(jsonFile, 'w') as outfile:
            json.dump(self.jsondict, outfile, indent=4)

        print("FUNCTION GENERATOR MEASUREMENT - DONE ARCHIVING" + "\n")
        self.status_archive_results = 1
class FEMB_CONFIG(FEMB_CONFIG_BASE):

    #__INIT__#
    def __init__(self):
        #declare basic system parameters
        self.NFEMBS = 4
        self.NASICS = 8
        self.NASICCH = 16

        #declare board specific registers
        self.FEMB_VER = "WIB_SBND"
        self.REG_RESET = 0
        self.REG_ASIC_RESET = 1
        self.REG_ASIC_SPIPROG = 2
        self.REG_SOFT_ADC_RESET = 1

        self.REG_LATCHLOC_3_TO_0 = 4
        self.REG_LATCHLOC_7_TO_4 = 14

        self.REG_FPGA_TP_EN = 16
        self.REG_ASIC_TP_EN = 16
        self.REG_DAC_SELECT = 16
        self.REG_TP = 5

        self.CLK_SELECT = 6
        self.CLK_SELECT2 = 15

        self.REG_SEL_ASIC = 7
        self.REG_SEL_ASIC_LSB = 8

        self.REG_WIB_MODE = 8
        self.REG_ADC_DISABLE = 8

        self.REG_HS_DATA = 9
        self.REG_HS = 17

        self.INT_TP_EN = 18
        self.EXT_TP_EN = 18

        self.REG_SPI_BASE = 0x200
        self.REG_SPI_RDBACK_BASE = 0x250
        
        self.REG_TEST_PAT = 3
        self.REG_TEST_PAT_DATA = 0x01230000

        #internal variables
        self.fembNum = 0
        self.wibNum = 0
        self.useExtAdcClock = True
        self.isRoomTemp = False
        self.doReSync = True
        self.spiStatus = 0x0
        self.syncStatus = 0x0
        self.CLKSELECT_val_RT = 0xFF
        self.CLKSELECT2_val_RT = 0xFF
        self.CLKSELECT_val_CT = 0xEF
        self.CLKSELECT2_val_CT = 0xEF
        self.REG_LATCHLOC_3_TO_0_val = 0x04040404
        self.REG_LATCHLOC_7_TO_4_val = 0x04040404
        self.fe_regs = [0x00000000]*(16+2)*8*8
        self.fe_REGS = [0x00000000]*(8+1)*4
        self.useLArIATmap = False #True

        #COTS shifts
        self.fe1_sft_RT = 0x00000000
        self.fe2_sft_RT = 0x00000000
        self.fe3_sft_RT = 0x00000000
        self.fe4_sft_RT = 0x00000000
        self.fe5_sft_RT = 0x00000000
        self.fe6_sft_RT = 0x00000000
        self.fe7_sft_RT = 0x00000000
        self.fe8_sft_RT = 0x00000000

        self.fe1_sft_CT = 0x00000000
        self.fe2_sft_CT = 0x00000000
        self.fe3_sft_CT = 0x00000000
        self.fe4_sft_CT = 0x00000000
        self.fe5_sft_CT = 0x00000000
        self.fe6_sft_CT = 0x00000000
        self.fe7_sft_CT = 0x00000000
        self.fe8_sft_CT = 0x00000000
            
        #COTS phases
        self.fe1_pha_RT = 0x00000000
        self.fe2_pha_RT = 0x00000000
        self.fe3_pha_RT = 0x00000000
        self.fe4_pha_RT = 0x00000000
        self.fe5_pha_RT = 0x00000000
        self.fe6_pha_RT = 0x00000000
        self.fe7_pha_RT = 0x00000000
        self.fe8_pha_RT = 0x00000000

        self.fe1_pha_CT = 0x00000000
        self.fe2_pha_CT = 0x00000000
        self.fe3_pha_CT = 0x00000000
        self.fe4_pha_CT = 0x00000000
        self.fe5_pha_CT = 0x00000000
        self.fe6_pha_CT = 0x00000000
        self.fe7_pha_CT = 0x00000000
        self.fe8_pha_CT = 0x00000000
        
        #initialize FEMB UDP object
        self.femb = FEMB_UDP()
        self.femb.UDP_PORT_WREG = 32000 #WIB PORTS
        self.femb.UDP_PORT_RREG = 32001
        self.femb.UDP_PORT_RREGRESP = 32002
        self.femb.doReadBack = False #WIB register interface is unreliable

        #ASIC config variables
        self.feasicLeakage = 0 #0 = 500pA, 1 = 100pA
        self.feasicLeakagex10 = 0 #0 = pA, 1 = pA*10
        self.feasicAcdc = 0 #AC = 0, DC = 1
        self.feasicBaseline = 0 #0 = 900mV, 1 = 200mV        
        self.feasicEnableTestInput = 0 #0 = disabled, 1 = enabled
        self.feasicGain = 2 #4.7,7.8,14,25
        self.feasicShape = 1 #0.5,1,2,3
        self.feasicBuf = 1 #0 = OFF, 1 = ON

        #Read in LArIAT mapping if desired

        if self.useLArIATmap:
            self.cppfr = CPP_FILE_RUNNER()            
            with open(self.cppfr.filename('configuration/configs/LArIAT_pin_mapping.map'), "rb") as fp:
                self.lariatMap = pickle.load(fp)
                
            #APA Mapping
            va = self.lariatMap
            va_femb = []
            for vb in va:
                if int(vb[9]) in (0,1,2,3,4) :
                    va_femb.append(vb)
            apa_femb_loc = []
            for chn in range(128):
                for vb in va_femb:
                    if int(vb[8]) == chn:
                        if (vb[1].find("Co")) >= 0 :#collection wire
                            chninfo = [ "X" + vb[0], vb[8], int(vb[6]), int(vb[7]), int(vb[9]), int(vb[10])]
                        elif (vb[1].find("In")) >= 0 : #induction wire
                            chninfo = [ "U" + vb[0], vb[8], int(vb[6]), int(vb[7]), int(vb[9]), int(vb[10])]
                        apa_femb_loc.append(chninfo)
            for chn in range(128):
                fl_w = True
                fl_i = 0
                for tmp in apa_femb_loc:
                    if int(tmp[1]) == chn:
                        fl_w = False
                        break
                if (fl_w):
                    chninfo = [ "V" + format(fl_i, "03d"), format(chn, "03d"), chn//16 , format(chn%15, "02d"), apa_femb_loc[0][4], apa_femb_loc[0][5]]
                    apa_femb_loc.append(chninfo)
                    fl_i = fl_i + 1

            self.All_sort = []
            self.X_sort = []
            self.V_sort = []
            self.U_sort = []
            for i in range(128):
                for chn in apa_femb_loc:
                    if int(chn[1][0:3]) == i :
                        self.All_sort.append(chn)
    
                    for chn in apa_femb_loc:
                        if chn[0][0] == "X" and int(chn[0][1:3]) == i :
                            self.X_sort.append(chn)
                    for chn in apa_femb_loc:
                        if chn[0][0] == "V" and int(chn[0][1:3]) == i :
                            self.V_sort.append(chn)
                    for chn in apa_femb_loc:
                        if chn[0][0] == "U" and int(chn[0][1:3]) == i :
                            self.U_sort.append(chn)

            self.WireDict = {}
            for line in self.All_sort:
                key = "wib{:d}_femb{:d}_chip{:d}_chan{:02d}".format(line[5],line[4],line[2],line[3])
                self.WireDict[key] = line[0]
                
    def printParameters(self):
        print("FEMB #             \t",self.fembNum)
        print("Room temperature   \t",self.isRoomTemp)
        print("Do resync          \t",self.doReSync)
        print("FE-ASIC leakage    \t",self.feasicLeakage)
        print("FE-ASIC leakage x10\t",self.feasicLeakagex10)
        print("FE-ASIC AD/DC      \t",self.feasicAcdc)
        print("FE-ASIC test input \t",self.feasicEnableTestInput)
        print("FE-ASIC baseline   \t",self.feasicBaseline)
        print("FE-ASIC gain       \t",self.feasicGain)
        print("FE-ASIC shape      \t",self.feasicShape)
        print("FE-ASIC buffer     \t",self.feasicBuf)

        print("FE-ASIC config")
        for regNum in range(self.REG_SPI_BASE,self.REG_SPI_BASE+72,1):
            regVal = self.femb.read_reg( regNum)
            if regVal == None:
                continue
            print( str(regNum) + "\t" + str(hex(regVal)) )

    def resetBoard(self):
        print("Reset")

    def initBoard(self):
        self.initWib()
        for femb in range(0,4,1):
            self.selectFemb(femb)
            self.initFemb()
        
    def initWib(self):
        #WIB initialization

        self.wib_switch()
        
        #set UDP ports to WIB registers
        self.wib_reg_enable()

        #register 2, LED
        #self.femb.write_reg_bits(2 , 0, 0xFF, 0 )

        #set jumbo size
        #self.femb.write_reg(0x1F,0xEFB)

        #set external clock
        self.femb.write_reg(0x4, 8)
        self.femb.write_reg(16,0x7F00)
        self.femb.write_reg(15,0)

        #sync timestamp /WIB
        self.femb.write_reg(1,0)
        self.femb.write_reg(1,0)
        self.femb.write_reg(1,2)
        self.femb.write_reg(1,2)                
        self.femb.write_reg(1,0)
        self.femb.write_reg(1,0)

        #Reset error /WIB
        self.femb.write_reg(18, 0x8000)
        self.femb.write_reg(18, 0x8000)

        #return register interface to FEMB
        self.selectFemb(self.fembNum)

    def initFemb(self):
        fembVal = self.fembNum - 4*(self.wibNum)
            
        if (fembVal < 0) or (fembVal >= self.NFEMBS ):
            return

        print("Initialize FEMB",fembVal)

        #FEMB power enable on WIB
        self.powerOnFemb(fembVal)

        #Make sure register interface is for correct FEMB
        self.selectFemb(fembVal)

        #check if FEMB register interface is working
        print("Checking register interface")
        regVal = self.femb.read_reg(6)
        if (regVal == None) or (regVal == -1):

            # try again
            self.powerOffFemb(fembVal)
            time.sleep(10)
            self.powerOnFemb(fembVal)

            newregVal = self.femb.read_reg(6)
            if (newregVal == None) or (newregVal == -1):
                
                print("Error - FEMB register interface is not working.")
                print(" Will not initialize FEMB.")
                return

        checkFirmware = self.checkFirmwareVersion()
        if checkFirmware == False:

            # try again
            self.powerOffFemb(fembVal)
            time.sleep(10)
            self.powerOnFemb(fembVal)

            newcheckFirmware = self.checkFirmwareVersion()
            if newcheckFirmware == False:

                print("Error - invalid firmware, will not attempt to initialize board")
                return

        #turn off pulser
        self.femb.write_reg_bits( self.REG_FPGA_TP_EN, 0,0x1,0) #test pulse enable
        self.femb.write_reg_bits( self.REG_ASIC_TP_EN, 1,0x1,0) #test pulse enable
        self.femb.write_reg_bits( self.REG_DAC_SELECT, 8,0x1,0) #test pulse enable
        self.femb.write_reg_bits( self.REG_TP, 0,0x1F,0x00) #test pulse amplitude
        self.femb.write_reg_bits( self.REG_TP, 16,0xFFFF,0x100) #test pulse frequency
        self.femb.write_reg_bits( self.REG_TP, 8,0xFF,0x00) #test pulse delay

        #Timestamp reset
        self.femb.write_reg(0, 4)
        self.femb.write_reg(0, 4)

        #Reset SPI
        self.femb.write_reg(self.REG_ASIC_RESET,1)
        self.femb.write_reg(self.REG_ASIC_RESET,1)
        self.femb.write_reg(self.REG_ASIC_RESET,2)
        self.femb.write_reg(self.REG_ASIC_RESET,2)

        self.femb.write_reg(self.REG_TEST_PAT, self.REG_TEST_PAT_DATA)

        #Turn off readback checking for ASIC config
        self.femb.doReadBack = False

        #ADC Setup
        self.set_cots_shift()
        
        #Set ASIC SPI configuration registers
        self.configFeAsic()

        #check ASIC SPI
        self.checkFembSpi()
        print("SPI STATUS","\t",self.spiStatus)

        #Enable Streaming
        self.femb.write_reg(9,9)
        self.femb.write_reg(9,9)
        time.sleep(0.1)

        # write to WIB
        self.wib_reg_enable()

        # check link status
        retry_links = False
        link_status = self.femb.read_reg(0x21)
        if (fembVal == 0):
            femb_link = link_status & 0xFF
        elif (fembVal == 1):
            femb_link = (link_status & 0xFF00)>>8
        elif (fembVal == 2):
            femb_link = (link_status & 0xFF0000)>>16
        elif (fembVal == 3):
            femb_link = (link_status & 0xFF000000)>>24
        if (not femb_link):
            retry_links = True
        else:
            print("HS links enabled")
            
        if (retry_links):
            #Enable Streaming
            self.selectFemb(fembVal)
            self.femb.write_reg(9,9)
            self.femb.write_reg(9,9)
            time.sleep(2)

            self.wib_reg_enable()
            print("linkstatus",hex(link_status))
            if (fembVal == 0):
                femb_link = link_status & 0xFF
            elif (fembVal == 1):
                femb_link = (link_status & 0xFF00)>>8
            elif (fembVal == 2):
                femb_link = (link_status & 0xFF0000)>>16
            elif (fembVal == 3):
                femb_link = (link_status & 0xFF000000)>>24
            if (not femb_link):
                print("HS link error, LINK STATUS:",hex(femb_link))
                return
            else:
                print("HS links enabled on retry")
                
        #reset the error counters
        self.femb.write_reg(20,3)
        self.femb.write_reg(20,3)
        time.sleep(0.001)
        self.femb.write_reg(20,0)
        self.femb.write_reg(20,0)
        time.sleep(0.001)

        # start streaming data from ASIC 0 in initialization
        self.femb.write_reg(7, 0x80000000)
        self.femb.write_reg(7, 0x80000000)
        femb_asic = 0 & 0x0F
        wib_asic = (((fembVal << 16)&0x000F0000) + ((femb_asic << 8) &0xFF00))
        self.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb.write_reg(7, wib_asic)
        self.femb.write_reg(7, wib_asic)

        # return to FEMB control
        self.selectFemb(fembVal)

        #Print some happy messages for shifters
        print("Finished initializing ASICs for WIB{:d} FEMB{:d}".format(self.wibNum,fembVal)) 

    #Test FEMB SPI working
    def checkFembSpi(self):
        print("Check ASIC SPI")
         
        self.spiStatus = 0

        for k in range(2):
            #Disable streaming
            self.femb.write_reg(9, 0x0)
            time.sleep(0.01)

            i = 0
            for regNum in range(self.REG_SPI_BASE,self.REG_SPI_BASE+len(self.fe_REGS),1):
                self.femb.write_reg( regNum, self.fe_REGS[i])
                i += 1
            time.sleep(0.01)
            self.femb.write_reg( self.REG_ASIC_SPIPROG, 1)

            if (k==1):
                for j in range(3):
                    self.spiStatus = 0
                    time.sleep(0.01)
                    readvals = []
                    for regNum in range(self.REG_SPI_RDBACK_BASE,self.REG_SPI_RDBACK_BASE+len(self.fe_REGS),1):
                        rdbckVal = self.femb.read_reg( regNum)
                        if rdbckVal == None :
                            print("Error - FEMB register interface is not working.")
                            return
                        else:
                            readvals.append(rdbckVal)
                        time.sleep(0.001)

                    for i in range(len(self.fe_REGS)):
                        if self.fe_REGS[i] != readvals[i] :
                            print(hex(self.fe_REGS[i]),"\t",hex(readvals[i]))
                            print("SPI readback failed.")
                            self.spiStatus = 1
                if self.spiStatus == 1:            
                    return
        self.femb.write_reg(9, 9)
        self.femb.write_reg(9, 9)
        time.sleep(0.1)
        

    def checkSync(self):
        print("Check ASIC SYNC")
        regVal = self.femb.read_reg(6)
        if regVal == None:
            print("doAsicConfigcheckFembSpi: Could not check SYNC status, bad")
            return
        syncVal = ((regVal >> 16) & 0xFFFF)
        self.syncStatus = syncVal

    #Setup talking to WIB
    def wib_switch(self):
        #Set IP addresses based in wib number:
        #For SBND-LArIAT
        #iplist = ["131.225.150.203","131.225.150.206"]
        #For BNL testing
        iplist = ["192.168.121.1"]
        self.femb.UDP_IP = iplist[self.wibNum]
    
    def wib_reg_enable(self):
        
        self.femb.UDP_PORT_WREG = 32000
        self.femb.UDP_PORT_RREG = 32001
        self.femb.UDP_PORT_RREGRESP = 32002
        self.femb.REG_SLEEP = 0.001

 

    #COTS Shift and Phase Settings
    def set_cots_shift(self):
        if self.isRoomTemp:
            print("Setting COTS Shifts for RT")
            self.femb.write_reg(21,self.fe1_sft_RT)
            self.femb.write_reg(29,self.fe1_pha_RT)
            self.femb.write_reg(22,self.fe2_sft_RT)
            self.femb.write_reg(30,self.fe2_pha_RT)
            self.femb.write_reg(23,self.fe3_sft_RT)
            self.femb.write_reg(31,self.fe3_pha_RT)
            self.femb.write_reg(24,self.fe4_sft_RT)
            self.femb.write_reg(32,self.fe4_pha_RT)
            self.femb.write_reg(25,self.fe5_sft_RT)
            self.femb.write_reg(33,self.fe5_pha_RT)
            self.femb.write_reg(26,self.fe6_sft_RT)
            self.femb.write_reg(34,self.fe6_pha_RT)
            self.femb.write_reg(27,self.fe7_sft_RT)
            self.femb.write_reg(35,self.fe7_pha_RT)
            self.femb.write_reg(28,self.fe8_sft_RT)
            self.femb.write_reg(36,self.fe8_pha_RT)
        else:
            print("Setting COTS Shifts for CT")
            self.femb.write_reg(21,self.fe1_sft_CT)
            self.femb.write_reg(29,self.fe1_pha_CT)
            self.femb.write_reg(22,self.fe2_sft_CT)
            self.femb.write_reg(30,self.fe2_pha_CT)
            self.femb.write_reg(23,self.fe3_sft_CT)
            self.femb.write_reg(31,self.fe3_pha_CT)
            self.femb.write_reg(24,self.fe4_sft_CT)
            self.femb.write_reg(32,self.fe4_pha_CT)
            self.femb.write_reg(25,self.fe5_sft_CT)
            self.femb.write_reg(33,self.fe5_pha_CT)
            self.femb.write_reg(26,self.fe6_sft_CT)
            self.femb.write_reg(34,self.fe6_pha_CT)
            self.femb.write_reg(27,self.fe7_sft_CT)
            self.femb.write_reg(35,self.fe7_pha_CT)
            self.femb.write_reg(28,self.fe8_sft_CT)
            self.femb.write_reg(36,self.fe8_pha_CT)
            
        self.femb.write_reg(8,0)
        self.femb.write_reg(8,0)
        time.sleep(0.02)
        self.femb.write_reg(8,0x10)
        self.femb.write_reg(8,0x10)

        
    #FEMB power enable on WIB
    def powerOnFemb(self,femb):
        fembVal = int(femb)
        if (fembVal < 0) or (fembVal > 3 ):
            return

        #set UDP ports to WIB registers
        self.wib_reg_enable()

        # read back existing power setting
        oldVal = self.femb.read_reg(8)
        #print("oldVal",oldVal)
        
        #FEMB power enable
        if(fembVal == 0):
            regVal = 0x31000F
        if(fembVal == 1):
            regVal = 0x5200F0
        if(fembVal == 2):
            regVal = 0x940F00
        if(fembVal == 3):
            regVal = 0x118F000

        pwrVal = regVal | oldVal

        self.femb.write_reg(8,0)
        time.sleep(1)
        self.femb.write_reg(8, pwrVal)
        time.sleep(2)
        
        regVal = self.femb.read_reg(8)
        if regVal == None:
            return
        print("FEMB Power on: ", hex(regVal))

        #set UDP ports back to normal
        self.selectFemb(self.fembNum)

    def powerOffFemb(self,femb):
        fembVal = int(femb)
        if (fembVal < 0) or (fembVal > 3 ):
            return

        #set UDP ports to WIB registers
        self.wib_reg_enable()

        # read back existing power setting
        oldVal = self.femb.read_reg(8)
                
        regVal = 0
        #FEMB power disable
        if(fembVal == 0 and (oldVal & 0xF) != 0):
            regVal = 0x31000F
        if(fembVal == 1 and (oldVal & 0xF0)>>4 != 0):
            regVal = 0x5200F0
        if(fembVal == 2 and (oldVal & 0xF00)>>8 != 0):
            regVal = 0x940F00
        if(fembVal == 3 and (oldVal & 0xF000)>>16 != 0):
            regVal = 0x118F000
        
        pwrVal = 0x100000 | (regVal ^ oldVal)
        
        self.femb.write_reg(8, pwrVal)
        
        regVal = self.femb.read_reg(8)
        if regVal == None:
            return
        print("FEMB Power off: ", hex(regVal))        
        
        #set UDP ports back to normal
        self.selectFemb(self.fembNum)
        
    def selectChannel(self,asic,chan):
        #print("Select channel")
        asicVal = int(asic)
        if (asicVal < 0 ) or (asicVal > self.NASICS):
            return

        #print("asicVal",asicVal)
        fembVal = self.fembNum
        #print("fembVal",fembVal)
        
        #set UDP ports to WIB
        self.wib_reg_enable()

        # start streaming data from ASIC 0 in initialization
        self.femb.write_reg(7, 0x80000000)
        self.femb.write_reg(7, 0x80000000)
        femb_asic = asicVal & 0x0F
        wib_asic = (((fembVal << 16)&0x000F0000) + ((femb_asic << 8) &0xFF00))
        self.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb.write_reg(7, wib_asic | 0x80000000)
        self.femb.write_reg(7, wib_asic)
        self.femb.write_reg(7, wib_asic)
        
        #select ASIC
        #print("Selecting ASIC " + str(asicVal) )
        self.femb.write_reg_bits(self.REG_SEL_ASIC , self.REG_SEL_ASIC_LSB, 0xF, asicVal )

        #Note: WIB data format streams all 16 channels, don't need to select specific channel

        # return to FEMB control
        self.selectFemb(fembVal)

        #Enable Streaming
        self.femb.write_reg(9,9)
        self.femb.write_reg(9,9)
        time.sleep(0.1)
        
    def configFeAsic(self):
        print("CONFIG ASICs")

        # #global config varibles
        feasicLeakageVal = int( self.feasicLeakage ) #0 = 500pA, 1 = 100pA
        feasicLeakagex10Val = int( self.feasicLeakagex10 ) #0 = x1, 1 = x10
        acdcVal = int( self.feasicAcdc ) #DC = 0, AC = 1
        
        #channel specific variables
        testVal = int( self.feasicEnableTestInput )
        baseVal = int( self.feasicBaseline ) #0 = 900mV, 1 = 200mV
        gainVal = int( self.feasicGain )
        shapeVal = int( self.feasicShape )
        bufVal = int( self.feasicBuf ) #0 = OFF, 1 = ON

        if (testVal < 0 ) or (testVal > 1):
            return
        if (baseVal < 0 ) or (baseVal > 1):
            return
        if (gainVal < 0 ) or (gainVal > 3):
            return
        if (shapeVal < 0 ) or (shapeVal > 3):
            return
        if (acdcVal < 0 ) or (acdcVal > 1):
            return
        if (bufVal < 0 ) or (bufVal > 1):
            return
        if (feasicLeakageVal < 0 ) or (feasicLeakageVal > 1 ):
            return
        if (feasicLeakagex10Val < 0) or (feasicLeakagex10Val > 1):
            return

        #gain
        gainArray = [0,2,1,3] #00=4.7, 10=7.8, 01=14, 11=25
        gainValCorrect = gainArray[gainVal]
        
        #shape
        shapeArray = [2,0,3,1] #00=1.0, 10=0.5, 01=3.0, 11=2.0
        shapeValCorrect = shapeArray[shapeVal]

        #datashift
        if self.isRoomTemp == True:
            self.femb.write_reg_bits(self.CLK_SELECT , 0, 0xFF, self.CLKSELECT_val_RT ) #clock select
            self.femb.write_reg_bits(self.CLK_SELECT2 , 0, 0xFF, self.CLKSELECT2_val_RT ) #clock select 2
        else:
            self.femb.write_reg_bits(self.CLK_SELECT , 0, 0xFF, self.CLKSELECT_val_CT ) #clock select
            self.femb.write_reg_bits(self.CLK_SELECT2 , 0, 0xFF,  self.CLKSELECT2_val_CT ) #clock select 2                    
        self.femb.write_reg_bits(self.REG_LATCHLOC_3_TO_0 , 0, 0xFFFFFFFF, self.REG_LATCHLOC_3_TO_0_val )
        self.femb.write_reg_bits(self.REG_LATCHLOC_7_TO_4 , 0, 0xFFFFFFFF, self.REG_LATCHLOC_7_TO_4_val )
        
        #COTS Register Settings
        sts = testVal
        snc = baseVal
        sg = gainValCorrect
        st = shapeValCorrect
        smn = 0 #Output monitor enabled: not currently an option in femb_python so keep at 0 for now
        sdf = bufVal
        chn_reg = ((sts&0x01)<<7) + ((snc&0x01)<<6) + ((sg&0x03)<<4) + ((st&0x03)<<2)  + ((smn&0x01)<<1) + ((sdf&0x01)<<0)

        #COTS Global Register Settings
        slk0 = feasicLeakageVal
        stb1 = 0 #Monitors not currently used in femb_python
        stb = 0 #Monitors not currently used in femb_python
        s16 = 0 #High filter in channel 16 disabled
        slk1 = feasicLeakagex10Val
        sdc = acdcVal
        swdac = 0 #For pulser, set elsewhere
        dac = 0 #For pulser, set elsewhere
        global_reg = ((slk0&0x01)<<0) + ((stb1&0x01)<<1) + ((stb&0x01)<<2)+ ((s16&0x01)<<3) + ((slk1&0x01)<<4) + ((sdc&0x01)<<5) +((00&0x03)<<6)
        dac_reg = (((dac&0x01)//0x01)<<7)+(((dac&0x02)//0x02)<<6)+\
                  (((dac&0x04)//0x04)<<5)+(((dac&0x08)//0x08)<<4)+\
                  (((dac&0x10)//0x10)<<3)+(((dac&0x20)//0x20)<<2)+\
                  (((swdac&0x03))<<0)
        
        for chip in range(self.NASICS):
            for chn in range(self.NASICCH):
                if self.useLArIATmap:
                    key = "wib{:d}_femb{:d}_chip{:d}_chan{:02d}".format(self.wibNum,self.fembNum,chip+1,chn) #Note map has chips 1-8, not 0-7
                    if self.WireDict[key][0] == "X":
                        snc = 0 #set baseline for collection
                    elif self.WireDict[key][0] == "U":
                        snc = 1 #set baseline for induction

                chn_reg = ((sts&0x01)<<7) + ((snc&0x01)<<6) + ((sg&0x03)<<4) + ((st&0x03)<<2)  + ((smn&0x01)<<1) + ((sdf&0x01)<<0)
                #print("chip",chip,"channel",chn,"chn_reg",hex(chn_reg))
                chn_reg_bool = []
                for j in range(8):
                    chn_reg_bool.append ( bool( (chn_reg>>j)%2 ))
                start_pos = (8*16+16)*chip + (16-chn)*8
                self.fe_regs[start_pos-8 : start_pos] = chn_reg_bool

            global_reg_bool = []
            for j in range(8):
                global_reg_bool.append ( bool( (global_reg>>j)%2 ) )
            for j in range(8):
                global_reg_bool.append ( bool( (dac_reg>>j)%2 ) )

            start_pos = (8*16+16)*chip + 16*8
            self.fe_regs[start_pos : start_pos+16] = global_reg_bool

        #Convert bits to 36 32-bit register words
        for chip in [0,2,4,6]:
            chip_bits_len = 8*(16+2)
            chip_fe_regs0 = self.fe_regs[   chip*chip_bits_len: (chip+1)* chip_bits_len]
            chip_fe_regs1 = self.fe_regs[   (chip+1)*chip_bits_len: (chip+2)* chip_bits_len]
            chip_regs = []
            for onebit in chip_fe_regs0:
                chip_regs.append(onebit)
            for onebit in chip_fe_regs1:
                chip_regs.append(onebit)
            len32 = len(chip_regs)//32
            if (len32 != 9):
                print("ERROR FE register mapping")
            else:
                for i in range(len32):
                    if ( i*32 <= len(chip_regs) ):
                        bits32 = chip_regs[i*32: (i+1)*32]
                        self.fe_REGS[int(chip/2*len32 + i) ] = (sum(v<<j for j, v in enumerate(bits32)))


        #turn off HS data before register writes
        self.femb.write_reg_bits(9 , 0, 0x1, 0 )
        print("HS link turned off")
        time.sleep(1)

        #run the SPI programming
        self.doAsicConfig()

        #turn HS link back on
        print("HS link turned back on")
        self.femb.write_reg_bits(9 , 0, 0x1, 1 )
        time.sleep(1)


    def doAsicConfig(self):
        print("Program ASIC SPI")

        for k in range(2):
            #Disable streaming
            self.femb.write_reg(9, 0x0)
            time.sleep(0.01)

            i = 0
            for regNum in range(self.REG_SPI_BASE,self.REG_SPI_BASE+len(self.fe_REGS),1):
                self.femb.write_reg( regNum, self.fe_REGS[i])
                self.femb.write_reg( regNum+36, self.fe_REGS[i])
                i += 1
            time.sleep(0.01)
            self.femb.write_reg( self.REG_ASIC_SPIPROG, 1)

        #self.printParameters()
        
        #Enable streaming
        self.femb.write_reg(9, 9)
        self.femb.write_reg(9, 9)
        time.sleep(0.1)

    def selectFemb(self, fembIn):
        fembVal = int( fembIn)
        if (fembVal < 0) or (fembVal > self.NFEMBS ):
            print("Invalid FEMB # requested")
            return
        self.fembNum = fembVal
        #print("selecting FEMB",fembVal)

        #set read/write ports
        if fembVal == 0:
            self.femb.UDP_PORT_WREG = 32016
            self.femb.UDP_PORT_RREG = 32017
            self.femb.UDP_PORT_RREGRESP = 32018

        if fembVal == 1:
            self.femb.UDP_PORT_WREG = 32032
            self.femb.UDP_PORT_RREG = 32033
            self.femb.UDP_PORT_RREGRESP = 32034

        if fembVal == 2:
            self.femb.UDP_PORT_WREG = 32048
            self.femb.UDP_PORT_RREG = 32049
            self.femb.UDP_PORT_RREGRESP = 32050

        if fembVal == 3:
            self.femb.UDP_PORT_WREG = 32064
            self.femb.UDP_PORT_RREG = 32065
            self.femb.UDP_PORT_RREGRESP = 32066

        #self.femb.write_reg(0, femb_asic)
        self.femb.write_reg(self.REG_HS,1)
        

        #slow down register interface for FEMBs
        self.femb.REG_SLEEP = 0.05
        time.sleep(0.1)

    def setFpgaPulser(self,enable,dac):

        enableVal = int(enable)
        print("set FPGA pulser",enableVal)

        if (enableVal < 0 ) or (enableVal > 1 ) :
            print( "femb_config_femb : setFpgaPulser - invalid enable value")
            return
        dacVal = int(dac)
        if ( dacVal < 0 ) or ( dacVal > 0x3F ) :
            print( "femb_config_femb : setFpgaPulser - invalid dac value")
            return

        self.femb.write_reg_bits( self.REG_FPGA_TP_EN, 0,0x3,enableVal) #test pulse enable
        self.femb.write_reg_bits( self.REG_FPGA_TP_EN, 8,0x1,enableVal) #test pulse enable
        self.femb.write_reg_bits( self.REG_TP , 0, 0x3F, dacVal ) #TP Amplitude
        self.femb.write_reg_bits( self.REG_TP , 8, 0xFF, 219 ) #DLY
        self.femb.write_reg_bits( self.REG_TP , 16, 0xFFFF, 497 ) #FREQ

        #set pulser enable bit
        if enableVal == 1 :
            self.femb.write_reg( self.EXT_TP_EN, 0x2) #this register is confusing, check
        else :
            self.femb.write_reg( self.EXT_TP_EN, 0x3) #pulser disabled

        #connect channel test input to external pin
        firstfourasics = int(self.NASICS/2)
        for asic in range(0,firstfourasics,1):
            baseReg = int(asic)*9

            self.fe_REGS[baseReg+4] = self.fe_REGS[baseReg+4] & 0xFFFF0000
            self.fe_REGS[baseReg+8] = self.fe_REGS[baseReg+8] & 0x0000FFFF
                
            if enableVal == 1:
                self.fe_REGS[baseReg+4] = self.fe_REGS[baseReg+4] | 0x2<<8
                self.fe_REGS[baseReg+8] = self.fe_REGS[baseReg+8] | 0x2<<24

        self.doAsicConfig()

    def setInternalPulser(self,enable,dac):

        enableVal = int(enable)
        print("set ASIC pulser",enableVal)
        
        if (enableVal < 0 ) or (enableVal > 1 ) :
            print( "femb_config_femb : setInternalPulser - invalid enable value")
            return
        dacVal = int(dac)
        if ( dacVal < 0 ) or ( dacVal > 0x3F ) :
            print( "femb_config_femb : setInternalPulser - invalid dac value")
            return

        self.femb.write_reg_bits( self.REG_DAC_SELECT, 8, 0x1, 0) #test pulse enable
        self.femb.write_reg_bits( self.REG_TP , 0, 0x3F, 0 ) #TP Amplitude
        self.femb.write_reg_bits( self.REG_TP , 8, 0xFF, 219 ) #DLY
        self.femb.write_reg_bits( self.REG_TP , 16, 0xFFFF, 497 ) #FREQ

        #set pulser enable bit
        if enableVal == 1 :
            self.femb.write_reg( self.INT_TP_EN, 0x2) #this register is confusing, check
        else :
            self.femb.write_reg( self.INT_TP_EN, 0x3) #pulser disabled

        dacVal = (dacVal & 0x3F)
        newDacVal = int('{:08b}'.format(dacVal)[::-1], 2)

        asicWord = ((newDacVal << 8 ) & 0xFFFF)
        if enableVal == 1 :
            asicWord = asicWord + (0x1 << 8)
        #print(hex(asicWord))
            
        #connect channel test input to external pin
        firstfourasics = int(self.NASICS/2)
        for asic in range(0,firstfourasics,1):
            baseReg = int(asic)*9

            self.fe_REGS[baseReg+4] = self.fe_REGS[baseReg+4] & 0xFFFF0000
            self.fe_REGS[baseReg+8] = self.fe_REGS[baseReg+8] & 0x0000FFFF
                
            if enableVal == 1:
                self.fe_REGS[baseReg+4] = self.fe_REGS[baseReg+4] | asicWord
                self.fe_REGS[baseReg+8] = self.fe_REGS[baseReg+8] | asicWord<<16

        self.doAsicConfig()

        if enableVal == 1:
            self.femb.write_reg_bits( self.REG_ASIC_TP_EN , 0, 0x3, 0x2 ) #NOTE, also disabling FPGA pulser here
        else:
            self.femb.write_reg_bits( self.REG_ASIC_TP_EN , 0, 0x3, 0x0 )

    def checkFirmwareVersion(self):
        #set UDP ports to WIB
        self.wib_reg_enable()

        #check WIB fw version reg
        wibVerReg = self.femb.read_reg(255)
        if wibVerReg == None :
            return False
        wibVerReg = (wibVerReg & 0xFFF)

        #set UDP ports back to normal
        self.selectFemb(self.fembNum)

        fembVerReg = self.femb.read_reg(257)

        if fembVerReg == None :
            return False
        fembVerReg = (fembVerReg & 0xFFF)

        if wibVerReg != 0x122 and wibVerReg != 0x111:
            print("Invalid WIB firmware version detected",hex(wibVerReg),"this configuration requires version 0x108 or 0x111")
            return False
        if fembVerReg != 0x501 :
            print("Invalid FEMB firmware version detected",hex(fembVerReg),"this configuration requires version 0x501")
            return False
        
        print( "WIB Firmware Version: " + str(hex(wibVerReg)) )
        print( "FEMB Firmware Version: " + str(hex(fembVerReg)) )

        #good firmware id
        return True

    def readCurrent(self):

        self.femb.UDP_PORT_WREG = 32000 #WIB PORTS
        self.femb.UDP_PORT_RREG = 32001
        self.femb.UDP_PORT_RREGRESP = 32002

        for j in range(0,100):
            self.femb.write_reg(5,0)
            self.femb.write_reg(5,0x10000)
            self.femb.write_reg(5,0)
            time.sleep(0.01)

        results = []
        for pwrSel in range(1,25):
            self.femb.write_reg(5,pwrSel)
            time.sleep(0.1)
            regVal = self.femb.read_reg(6)
            if regVal == None:
                 results.append(0)
                 continue
                 #return None
            val = regVal & 0xFFFFFFFF
            results.append(val)

        self.selectFemb(0)
        return results
Example #16
0
class FEMB_TEST(object):
    def __init__(self):

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA()
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000

        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0
        self.fembNum = 0

        self.cppfr = CPP_FILE_RUNNER()

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("SIMPLE MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        #check local directory structure, available space
        if os.path.isdir("./data") == False:
            print("Error running doFembTest - data directory not found.")
            print(
                " Please check that femb_python package directory structure is intact."
            )
            return

        #select femb
        self.femb_config.selectFemb(self.fembNum)

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(5)
        if (regVal == None) or (regVal == -1):
            print(
                "Error running doFembTest - FEMB register interface is not working."
            )
            print(" Turn on or debug FEMB UDP readout.")
            return
        print("Read register 5, value = " + str(hex(regVal)))

        #for regNum in range (0,1024,1):
        #    regVal = self.femb_config.femb.read_reg(regNum)
        #    print(str(regNum) + "\t" + str( hex( regVal ) ) )

        #initialize FEMB to known state
        print("Initializing board")
        self.femb_config.initFemb(self.fembNum)

        #check if data streaming is working
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return
        if len(testData) == 0:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            #print(" This script will exit now")
            #sys.exit(0)
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists(
                'test_measurements/wibTestStand/parseBinaryFile'):
            print('parseBinaryFile not found, run setup.sh')
            #sys.exit(0)
            return

        print("SIMPLE MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print("Please run check_setup method before trying to take data")
            return
        if self.status_record_data == 1:
            print(
                "Data already recorded. Reset/restat GUI to begin a new measurement"
            )
            return
        #MEASUREMENT SECTION
        print("SIMPLE MEASUREMENT - RECORDING DATA")

        #initialize FEMB configuration to known state
        #self.femb_config.configFeAsic(0,0,0)

        #wait to make sure HS link is back on
        sleep(0.5)

        #set output file
        self.write_data.filedir = "data/"
        self.write_data.filename = "rawdata_simpleMeasurement_" + str(
            self.write_data.date) + ".bin"
        print("Recording " + self.write_data.filename)
        self.write_data.numpacketsrecord = 100
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        #setup output file and record data
        self.write_data.open_file()
        subrun = 0
        asicCh = 0
        for asic in range(0, 8, 1):
            self.femb_config.selectChannel(asic, asicCh)
            self.write_data.record_data(subrun, asic, asicCh)
        self.write_data.close_file()

        #reset configuration to known state
        #self.femb_config.configFeAsic(0,0,0)

        print("SIMPLE MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Analysis already complete")
            return
        #ANALYSIS SECTION
        print("SIMPLE MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run(
            'test_measurements/wibTestStand/parseBinaryFile',
            [str(self.write_data.filedir) + str(self.write_data.filename)])

        #run analysis program
        newName = "output_parseBinaryFile_" + self.write_data.filename + ".root"
        call([
            "mv", "output_parseBinaryFile.root",
            str(self.write_data.filedir) + str(newName)
        ])
        self.cppfr.run(
            "test_measurements/wibTestStand/processNtuple_simpleMeasurement",
            [str(self.write_data.filedir) + str(newName)])

        #move result to data directory
        newName = "output_processNtuple_simpleMeasurement_" + self.write_data.filename + ".root"
        call([
            "mv", "output_processNtuple_simpleMeasurement.root",
            str(self.write_data.filedir) + str(newName)
        ])
        newName = "summaryPlot_" + self.write_data.filename + ".png"
        call([
            "mv", "summaryPlot_simpleMeasurement.png",
            str(self.write_data.filedir) + str(newName)
        ])

        #summary plot
        print(
            "SIMPLE MEASUREMENT - DISPLAYING SUMMARY PLOT, CLOSE PLOT TO CONTINUE"
        )
        call(["display", str(self.write_data.filedir) + str(newName)])

        print("SIMPLE MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA" +
              "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        if self.status_do_analysis == 0:
            print("Please analyze data before archiving results")
            return
        if self.status_archive_results == 1:
            print("Results already archived")
            return
        #ARCHIVE SECTION
        print("SIMPLE MEASUREMENT - STORE RESULTS IN DATABASE")
        #placeholder
        print("SIMPLE MEASUREMENT - DONE STORING RESULTS IN DATABASE" + "\n")
        self.status_archive_results = 1
class FEMB_TEST_GAIN(object):

    def __init__(self, datadir="data", outlabel="gainMeasurement",fembNum=0):
        #set internal variables
        self.datadir = datadir
        self.outlabel = outlabel + str("_femb_") + str(fembNum)
        self.outpathlabel = os.path.join(self.datadir, self.outlabel)
        self.fembNum = int(fembNum)

        print( "FEMB # " + str(fembNum) )

        #import femb_udp modules from femb_udp package
        self.femb_config = CONFIG()
        self.write_data = WRITE_DATA(self.datadir)
        #set appropriate packet size
        self.write_data.femb.MAX_PACKET_SIZE = 8000
        self.cppfr = CPP_FILE_RUNNER()
	
        #set status variables
        self.status_check_setup = 0
        self.status_record_data = 0
        self.status_do_analysis = 0
        self.status_archive_results = 0

        #misc variables
        self.gain = 0
        self.shape = 0
        self.base = 0
        self.leakage = 0
        self.leakagex10 = 0
        self.buffer = 0
        self.acdc = 0
        self.useInternalPulser = False
        self.useExtAdcClock = False
        self.isRoomTemp = False

        #json output, note module version number defined here
        self.jsondict = {'type':'fembTest_gain'}
        self.jsondict['version'] = '1.0'
        self.jsondict['timestamp']  = str(self.write_data.date)

    def check_setup(self):
        #CHECK STATUS AND INITIALIZATION
        print("GAIN MEASUREMENT - CHECKING READOUT STATUS")
        self.status_check_setup = 0

        #make sure output directory exists
        self.write_data.assure_filedir()

        #check if register interface is working
        print("Checking register interface")
        regVal = self.femb_config.femb.read_reg(6)
        if (regVal == None):
            print("Error running doFembTest - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")       
            return
        if ( regVal < 0 ):
            print("Error running doFembTest - FEMB register interface is not working.")
            print(" Turn on or debug FEMB UDP readout.")       
            return
        print("Read register 6, value = " + str( hex( regVal ) ) )

        #check that femb number is valid
        if ( int(self.fembNum) < 0 ) or ( int( self.fembNum) >= self.femb_config.NFEMBS ):
            print("Error running doFembTest - Invalid FEMB # specified.")
            return    

        #assign FEMB # to test 
        self.femb_config.selectFemb(self.fembNum)

        #initialize FEMB to known state
        print("Initializing board")
        self.femb_config.feasicGain = self.gain
        self.femb_config.feasicShape = self.shape
        self.femb_config.feasicBaseline = self.base
        self.femb_config.feasicLeakageVal = self.leakage
        self.femb_config.feasicLeakagex10Val = self.leakagex10
        self.femb_config.bufVal = self.buffer
        self.femb_config.acdcVal = self.acdc
        self.femb_config.feasicEnableTestInput = 0 #important
        self.femb_config.useExtAdcClock = self.useExtAdcClock
        self.femb_config.isRoomTemp = self.isRoomTemp
        #self.femb_config.printParameters()
        self.femb_config.initFemb()

        #test firmware versions
        if self.femb_config.checkFirmwareVersion() == False:
            print('Error running doFembTest - Invalid firmware and/or register read error')
            return

        #check if data streaming is working
        print("Checking data streaming")
        testData = self.write_data.femb.get_data_packets(1)
        if testData == None:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return
        if len(testData) == 0:
            print("Error running doFembTest - FEMB is not streaming data.")
            print(" Turn on and initialize FEMB UDP readout.")
            return

        print("Received data packet " + str(len(testData[0])) + " bytes long")

        #check for analysis executables
        if not self.cppfr.exists('test_measurements/fembTest/code/parseBinaryFile'):    
            print('parseBinaryFile not found, run setup.sh')
            return

        print("GAIN MEASUREMENT - READOUT STATUS OK" + "\n")
        self.status_check_setup = 1

    def record_data(self):
        if self.status_check_setup == 0:
            print("Please run check_setup method before trying to take data")
            return
        if self.status_record_data == 1:
            print("Data already recorded. Reset/restat GUI to begin a new measurement")
            return

        #MEASUREMENT SECTION
        print("GAIN MEASUREMENT - RECORDING DATA")

        #wait to make sure HS link is back on after check_setup
        sleep(5)

        #setup output file
        self.write_data.filename = self.outlabel+".bin"
        print("Recording " + self.write_data.filename )

        isOpen = self.write_data.open_file()
        if isOpen == 0 :
            print( "Error running doFembTest - Could not open output data file for writing, ending test" )
        subrun = 0

        #config FE ASICs
        print("FE ASIC Settings: Gain " + str(self.gain) + ", Shaping Time " + str(self.shape) + ", Baseline " + str(self.base) )
        print("FE ASIC Settings: Leakage Current " + str(self.leakage) + ", Leakage x10 " + str(self.leakagex10) )
        print("FE ASIC Settings: Output Buffer " + str(self.buffer) + ", AC/DC " + str(self.acdc) )
        self.femb_config.feasicGain = self.gain
        self.femb_config.feasicShape = self.shape
        self.femb_config.feasicBaseline = self.base
        self.femb_config.feasicLeakageVal = self.leakage
        self.femb_config.feasicLeakagex10Val = self.leakagex10
        self.femb_config.bufVal = self.buffer
        self.femb_config.acdcVal = self.acdc
        self.femb_config.feasicEnableTestInput = 0 #important
        self.femb_config.useExtAdcClock = self.useExtAdcClock
        self.femb_config.isRoomTemp = self.isRoomTemp
        self.femb_config.configFeAsic()

        #disable pulsers
        self.femb_config.setInternalPulser(0,0x0)
        self.femb_config.setFpgaPulser(0,0x0)

        self.femb_config.printParameters()

        #record data
        self.write_data.numpacketsrecord = 500
        self.write_data.run = 0
        self.write_data.runtype = 0
        self.write_data.runversion = 0

        #take initial noise data run
        subrun = 0
        asicCh = 0
        for asic in range(0,self.femb_config.NASICS,1):
          self.femb_config.selectChannel(asic,asicCh)
          self.write_data.record_data(subrun, asic, asicCh)

        #turn ASIC test input on, start pulser section
        self.femb_config.feasicEnableTestInput = 1
        self.femb_config.configFeAsic()
        if self.useInternalPulser == False :
            self.femb_config.setFpgaPulser(1,0)
        else:
            self.femb_config.setInternalPulser(1,0)
        subrun = 1

        #loop over pulser configurations, each configuration is it's own subrun
        for p in range(0,10,1):
            pVal = int(p)
            if self.useInternalPulser == False :
                self.femb_config.setFpgaPulser(1,pVal)
            else:
                self.femb_config.setInternalPulser(1,pVal)
            print("Pulse amplitude " + str(pVal) )

            #loop over channels
            for asic in range(0,8,1):
                self.femb_config.selectChannel(asic,asicCh)
                self.write_data.record_data(subrun, asic, asicCh)

            #increment subrun, important
            subrun = subrun + 1

        #close file
        self.write_data.close_file()

        #turn off FEMB
        self.femb_config.powerOffFemb(self.fembNum)

        print("GAIN MEASUREMENT - DONE RECORDING DATA" + "\n")
        self.status_record_data = 1

    def do_analysis(self):
        if self.status_record_data == 0:
            print("Please record data before analysis")
            return
        if self.status_do_analysis == 1:
            print("Analysis already complete")
            return
        #ANALYSIS SECTION
        print("GAIN MEASUREMENT - ANALYZING AND SUMMARIZING DATA")

        #parse binary
        self.cppfr.run("test_measurements/fembTest/code/parseBinaryFile", [self.write_data.data_file_path])

        #run analysis program
        parseBinaryFile = self.outpathlabel + "-parseBinaryFile.root"
        call(["mv", "output_parseBinaryFile.root" , parseBinaryFile])
        if self.useInternalPulser == False : 
            self.cppfr.run("test_measurements/fembTest/code/processNtuple_gainMeasurement",  [parseBinaryFile])
        else :
            self.cppfr.run("test_measurements/fembTest/code/processNtuple_gainMeasurement",  [parseBinaryFile,"1"])

        processNtupleFile = self.outpathlabel + "-processNtupleFile.root"
        call(["mv", "output_processNtuple_gainMeasurement.root" , processNtupleFile])

        summaryPlot = self.outpathlabel + "-summaryPlot.png"
        call(["mv", "summaryPlot_gainMeasurement.png" , summaryPlot])

        resultsFile = self.outpathlabel + "-results.list"
        call(["mv", "output_processNtuple_gainMeasurement.list" , resultsFile])

        print("GAIN MEASUREMENT - DONE ANALYZING AND SUMMARIZING DATA" + "\n")
        self.status_do_analysis = 1

    def archive_results(self):
        #if self.status_check_setup == 0 :
        #     print("Check setup status is 0, not archiving data")
        #     return
        #if self.status_do_analysis == 0:
        #    print("Please analyze data before archiving results")
        #    return
        if self.status_archive_results == 1:
            print("Results already archived")
            return
        #ARCHIVE SECTION
        print("GAIN MEASUREMENT - ARCHIVE")

        #add summary variables to output
        self.jsondict['status_check_setup'] = str(self.status_check_setup)
        self.jsondict['status_record_data'] = str(self.status_record_data)
        self.jsondict['status_do_analysis'] = str(self.status_do_analysis)
        self.jsondict['status_archive_results'] = str(1)
        self.jsondict['filedir'] = str(self.write_data.filedir )
        self.jsondict['config_gain'] = str(self.gain)
        self.jsondict['config_shape'] = str(self.shape)
        self.jsondict['config_base'] = str(self.base)
        self.jsondict['useInternalPulser'] = str(self.useInternalPulser)
        self.jsondict['syncStatus'] = str(self.femb_config.syncStatus)

        if self.status_do_analysis == 1:
          #parse the output results, kind of messy
          listFile = self.outpathlabel + "-results.list"

          lines = []
          with open( listFile ) as infile:
            for line in infile:
                line = line.strip('\n')
                line = line.split(',') #measurements separated by commas
                parseline = {}
                for n in range(0,len(line),1):
                    word = line[n].split(' ')
                    if( len(word) != 2 ):
                        continue
                    parseline[ str(word[0]) ] = str(word[1])
                lines.append(parseline)
            self.jsondict['results'] = lines

        #dump results into json
        jsonFile = self.outpathlabel + "-results.json"
        with open( jsonFile , 'w') as outfile:
            json.dump( self.jsondict, outfile, indent=4)

        print("GAIN MEASUREMENT - DONE STORING RESULTS IN DATABASE" + "\n")
        self.status_archive_results = 1