class TRACE_FFT_WINDOW_WIB(Gtk.Window): """ This window displays a live ADC redout and its FFT """ def __init__(self): Gtk.Window.__init__(self, title="ADC View Window") self.set_default_size(800, 800) self.figure = Figure(figsize=(8, 8), dpi=100) sw = Gtk.ScrolledWindow() self.add(sw) # A scrolled window border goes outside the scrollbars and viewport sw.set_border_width(10) canvas = FigureCanvas(self.figure) # a Gtk.DrawingArea canvas.set_size_request(750, 750) sw.add_with_viewport(canvas) self.show_all() self.sw = sw self.canvas = canvas self.femb = None self.reset() def reset(self): self.femb = FEMB_UDP() self.figure.clf() self.ax1 = self.figure.add_subplot(211) self.ax2 = self.figure.add_subplot(212) self.plot1 = self.ax1.plot([], []) self.plot2 = self.ax2.plot([], []) self.ani = animation.FuncAnimation(self.figure, self.plotData, interval=1000) #, blit=True) self.canvas.draw() def plotData(self, iFrame): self.ax1.cla() self.ax2.cla() self.ax1.set_xlabel("Time [us]") self.ax1.set_ylabel("Sample Value [ADC Counts]") self.ax2.set_xlabel("Frequency [MHz]") self.ax2.set_ylabel("|Y(freq)|") t, adc, frq, ampl = self.getTraceAndFFT() if t == None: return None self.plot1 = self.ax1.plot(t, adc) self.plot2 = self.ax2.plot(frq, ampl, 'r') self.canvas.draw() return self.plot1 def getTraceAndFFT(self): """ Gets trace from FEMB and returns 4 1D arrays: times, ADC counts, frequencies, Amplitude """ Yfft_total = [] first = 1 #data = self.femb.get_data(10) data = self.femb.get_data_packets(1) if data == None: #time.sleep(1.) return None, None, None, None if len(data) == 0: #time.sleep(1.) return None, None, None, None xpoint = [] ypoint = [] num = 0 print("HERE") for samp in data: print(samp) return None, None, None, None for samp in data: chNum = ((samp >> 12) & 0xF) sampVal = (samp & 0xFFF) #print str(chNum) + "\t" + str(sampVal) + "\t" + str( hex(sampVal) ) #if chNum == 0: xpoint.append(num * 0.5) ypoint.append(sampVal) num = num + 1 xarr = np.array(xpoint) yarr = np.array(ypoint) Fs = 2.0 # sampling rate Ts = 1.0 / Fs # sampling interval t = np.arange(0, 1, Ts) # time vector n = len(yarr) # length of the signal k = np.arange(n) T = n / Fs frq = k / T # two sides frequency range frq = frq[:n // 2] # one side frequency range Yfft = np.fft.fft(yarr) / n # fft computing and normalization Yfft = Yfft[:n // 2] frq = frq[1:] Yfft = Yfft[1:] #do averaging and normalization, very messy pos = 0 total = 0 for x in np.nditer(Yfft): #print abs(x) total = total + abs(x) if first == 1: Yfft_total.append(abs(x)) else: Yfft_total[pos] = Yfft_total[pos] + abs(x) pos = pos + 1 first = 0 if total < 0: #time.sleep(0.1) return None, None, None, None pos = 0 Yfft_norm = [] for bin in Yfft_total: Yfft_norm.append(bin / total) return xarr, yarr, frq, Yfft_norm
class FEMB_CONFIG(FEMB_CONFIG_BASE): def __init__(self,exitOnError=True): super().__init__(exitOnError=exitOnError) #declare board specific registers self.FEMB_VER = "adctestP1single" self.REG_RESET = 0 self.REG_ASIC_RESET = 1 self.REG_ASIC_SPIPROG = 2 self.REG_SEL_CH = 7 self.REG_HS = 17 self.REG_FESPI_BASE = 0x250 # 592 in decimal self.REG_ADCSPI_BASE = 0x200 # 512 in decimal self.REG_FESPI_RDBACK_BASE = 0x278 # 632 in decimal self.REG_ADCSPI_RDBACK_BASE = 0x228 # 552 in decimal self.REG_LATCHLOC1_4 = 4 self.REG_LATCHLOC5_8 = 14 self.REG_CLKPHASE = 6 self.REG_LATCHLOC1_4_data = 0x6 self.REG_LATCHLOC5_8_data = 0x0 self.REG_CLKPHASE_data = 0xfffc0000 self.REG_LATCHLOC1_4_data_1MHz = 0x5 self.REG_LATCHLOC5_8_data_1MHz = 0x0 self.REG_CLKPHASE_data_1MHz = 0xffff0000 self.REG_LATCHLOC1_4_data_cold = 0x6 self.REG_LATCHLOC5_8_data_cold = 0x0 self.REG_CLKPHASE_data_cold = 0xfffc0000 self.REG_LATCHLOC1_4_data_1MHz_cold = 0x4 self.REG_LATCHLOC5_8_data_1MHz_cold = 0x0 self.REG_CLKPHASE_data_1MHz_cold = 0xfffc0001 self.ADC_TESTPATTERN = [0x12, 0x345, 0x678, 0xf1f, 0xad, 0xc01, 0x234, 0x567, 0x89d, 0xeca, 0xff0, 0x123, 0x456, 0x789, 0xabc, 0xdef] ################################## # external clock control registers ################################## self.FPGA_FREQ_MHZ = 200 # frequency of FPGA clock in MHz self.REG_EXTCLK_RD_EN_OFF = 23 self.REG_EXTCLK_ADC_OFF = 21 self.REG_EXTCLK_ADC_WID = 22 self.REG_EXTCLK_MSB_OFF = 25 self.REG_EXTCLK_MSB_WID = 26 self.REG_EXTCLK_PERIOD = 20 self.REG_EXTCLK_LSB_FC_WID2 = 32 self.REG_EXTCLK_LSB_FC_OFF1 = 29 self.REG_EXTCLK_RD_EN_WID = 24 self.REG_EXTCLK_LSB_FC_WID1 = 30 self.REG_EXTCLK_LSB_FC_OFF2 = 31 self.REG_EXTCLK_LSB_S_WID = 28 self.REG_EXTCLK_LSB_S_OFF = 27 self.REG_EXTCLK_INV = 33 ################################## ################################## self.NASICS = 1 self.FUNCGENINTER = Keysight_33600A("/dev/usbtmc1",1) self.POWERSUPPLYINTER = RigolDP800("/dev/usbtmc0",["CH2","CH3","CH1"]) # turn on CH2 first self.F2DEFAULT = 0 self.CLKDEFAULT = "fifo" ## Firmware update related variables self.FIRMWAREPATH2MHZ = "/home/oper/Documents/CarlosForkedRepo/femb_python/femb_python/test_measurements/adc_clock_test/code/S_SKT_ADC_CHP_TST.sof" #self.FIRMWAREPATH1MHZ = "/opt/sw/releases/femb_firmware-0.1.0/adc_tester/S7_1M_SBND_FPGA.sof" self.FIRMWAREPROGEXE = "/opt/sw/intelFPGA/17.0/qprogrammer/bin/quartus_pgm" #self.FIRMWAREPROGCABLE = "USB-Blaster" self.FIRMWAREPROGCABLE = "USB-BlasterII" self.SAMPLERATE = 2e6 #initialize FEMB UDP object self.femb = FEMB_UDP() self.adc_reg = ADC_ASIC_REG_MAPPING() def resetFEMBBoard(self): #cp 1/17/18 # # resetFEMBBoard() # sends a 1 to register 1 for "instantaneous" ASIC reset. # sends a 0 to register 1 to ensure reset is not locked in. # # procedure: # line 29: FPGA to ASIC reset # line 30: wait 5 ms # line 31: FPGA to ASIC disable reset # print (" FEMB_CONFIG--> Reset FEMB (10 seconds) --") #Reset FEMB system self.femb.write_reg ( self.REG_RESET, 1) time.sleep(5.) self.femb.write_reg ( self.REG_RESET, 0) time.sleep(2.) print (" FEMB_CONFIG--> Reset FEMB is DONE\n") def initBoard(self): """ % initBoard() % set up default registers. % first wave in setting clock settings. """ print ("FEMB_CONFIG--> initBoard() -> Initialize FEMB --") # Frame size is multiple of 13, so 0xFACE is consistently the first 2 bytes. frame_size = settings.frame_size if (frame_size%13 != 0): frame_size = 13 * (frame_size//13) self.femb.write_reg(10, frame_size) time.sleep(0.1) if (self.femb.read_reg(10) != frame_size): sys.exit("FEMB_CONFIG--> initBoard() -> Frame Size not set correctly, something wrong with FPGA communication") print ("FEMB_CONFIG--> initBoard() -> Chip tester version {}".format(hex(self.femb.read_reg(0x101)))) # Set to WIB Mode and start by reading out chip 1 # Channel Setting is irrelevant in WIB mode self.femb.write_reg(8, 0x80000001) # WIB_MODE <= reg8_p(0) self.femb.write_reg(7, 0x80000000) # CHN_select <= reg7_p(7 downto 0) """ SHIFT DATA BUS """ # LATCH_LOC_0 <= reg4_p(7 downto 0) self.femb.write_reg(settings.LATCHLOC_reg, settings.LATCHLOC_data) """ SHIFT DATA BUS """ # CLK_selectx <= reg6_p(7 downto 0) self.femb.write_reg(settings.CLKPHASE_reg, settings.CLKPHASE_data) # self.femb.write_reg( 9, 0) # Write Coarse Clock Control self.femb.write_reg(21, settings.reg21_value[0]) self.femb.write_reg(21, settings.reg21_value[1]) self.femb.write_reg(21, settings.reg21_value[2]) self.femb.write_reg(21, settings.reg21_value[3]) self.femb.write_reg(21, settings.reg21_value[4]) self.femb.write_reg(21, settings.reg21_value[5]) self.femb.write_reg(22, settings.reg22_value[0]) # RESET Offset self.femb.write_reg(23, settings.reg23_value[0]) # RESET Width self.femb.write_reg(24, settings.reg24_value[0]) # READ Offset self.femb.write_reg(25, settings.reg25_value[0]) # READ Width self.femb.write_reg(26, settings.reg26_value[0]) # IDXM Offset self.femb.write_reg(27, settings.reg27_value[0]) # IDXM Width self.femb.write_reg(28, settings.reg28_value[0]) # IDXL Offset self.femb.write_reg(29, settings.reg29_value[0]) # IDXL Width self.femb.write_reg(30, settings.reg30_value[0]) # IDL1 Offset self.femb.write_reg(31, settings.reg31_value[0]) # IDL1 Width self.femb.write_reg(32, settings.reg32_value[0]) # IDL2 Offset self.femb.write_reg(33, settings.reg33_value[0]) # IDL2 Width #Fine Control self.femb.write_reg(34, settings.reg34_value[0]) # C0 & C1 fine clock settings self.femb.write_reg(35, settings.reg35_value[0]) # C2 & C3 fine clock settings self.femb.write_reg(36, settings.reg36_value[0]) # C2 & C3 fine clock settings #set default value to FEMB ADCs #clk = 2 is external #clk = 0 is internal self.adc_reg.set_adc_board( d=0, pcsr=0, pdsr=0, slp=0, tstin=1, clk = 0, frqc = 1, en_gr = 0, f0 = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 1, slsb = 0) # set to internal 1/31/18 cp self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0x30) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) self.configAdcAsic() print (" FEMB_CONFIG--> initBOARD() -> Initialize FEMB is DONE\n") """ def syncADC(self): # syncADC() # # procedures: # 1. set channel/global registers ensure F5=1, so # test data is selected and pipelined. Just as # in labview. # 2. configure ADC ASIC # 3. print ("\n FEMB_CONFIG--> Start sync ADC--") self.select_chn(1) # channel 0 & write clocks self.select_chn(3) # channel 0 & write clocks self.select_chn(1) # channel 0 & write clocks self.adc_reg.set_adc_global(chip = settings.chip_num, f5 = 1) # Test DATA self.configAdcAsic() print (" FEMB_CONFIG --> syncADC() -> Test ADC {}".format(settings.chip_num)) print (" FEMB_CONFIG --> syncADC() -> self.adc_reg.set_adc_global() \n") # for i in range(10,20,1): # print ("Register {} {}".format(i, hex(self.femb.read_reg(i)))) unsync = self.testUnsyncNew(settings.chip_num) if unsync != True: print (" FEMB_CONFIG --> ADC {} not synced, try to fix".format(settings.chip_num)) response = self.fixUnsyncNew(a) if (response != True): sys.exit (" FEMB_CONFIG --> ADC {} could not sync".format(settings.chip_num)) elif (unsync == True): print ("FEMB_CONFIG--> ADC {} synced!".format(settings.chip_num)) self.adc_reg.set_adc_global(chip = settings.chip_num, f5 = 1) self.configAdcAsic() self.REG_LATCHLOC1_4_data = self.femb.read_reg( settings.LATCHLOC_reg) self.REG_CLKPHASE_data = self.femb.read_reg( settings.CLKPHASE_reg) print ("FEMB_CONFIG--> Final Latch latency " + str(hex(self.REG_LATCHLOC1_4_data))) print ("FEMB_CONFIG--> Final Phase Shift " + str(hex(self.REG_CLKPHASE_data))) self.FinalSyncCheck() print ("FEMB_CONFIG--> ADC passed Sync Test!") """ def syncADC(self,iASIC=None): #turn on ADC test mode print("FEMB_CONFIG--> Start sync ADC") reg3 = self.femb.read_reg (3) newReg3 = ( reg3 | 0x80000000 ) self.femb.write_reg ( 3, newReg3 ) #31 - enable ADC test pattern time.sleep(0.1) alreadySynced = True for a in range(0,self.NASICS,1): print("FEMB_CONFIG--> Test ADC " + str(a)) unsync, syncDicts = self.testUnsync(a) if unsync != 0: alreadySynced = False print("FEMB_CONFIG--> ADC not synced, try to fix") self.fixUnsync(a) latchloc1_4 = self.femb.read_reg ( self.REG_LATCHLOC1_4 ) latchloc5_8 = self.femb.read_reg ( self.REG_LATCHLOC5_8 ) clkphase = self.femb.read_reg ( self.REG_CLKPHASE ) if self.SAMPLERATE == 1e6: if self.COLD: self.REG_LATCHLOC1_4_data_1MHz_cold = latchloc1_4 self.REG_LATCHLOC5_8_data_1MHz_cold = latchloc5_8 self.REG_CLKPHASE_data_1MHz_cold = clkphase else: self.REG_LATCHLOC1_4_data_1MHz = latchloc1_4 self.REG_LATCHLOC5_8_data_1MHz = latchloc5_8 self.REG_CLKPHASE_data_1MHz = clkphase else: # 2 MHz if self.COLD: self.REG_LATCHLOC1_4_data_cold = latchloc1_4 self.REG_LATCHLOC5_8_data_cold = latchloc5_8 self.REG_CLKPHASE_data_cold = clkphase else: self.REG_LATCHLOC1_4_data = latchloc1_4 self.REG_LATCHLOC5_8_data = latchloc5_8 self.REG_CLKPHASE_data = clkphase print("FEMB_CONFIG--> Latch latency {:#010x} {:#010x} Phase: {:#010x}".format(latchloc1_4, latchloc5_8, clkphase)) self.femb.write_reg ( 3, (reg3&0x7fffffff) ) self.femb.write_reg ( 3, (reg3&0x7fffffff) ) print("FEMB_CONFIG--> End sync ADC") return not alreadySynced,latchloc1_4,latchloc5_8 ,clkphase def testUnsync(self, adc, npackets=10): print("Starting testUnsync adc: ",adc) adcNum = int(adc) if (adcNum < 0 ) or (adcNum > 7 ): print("FEMB_CONFIG--> femb_config_femb : testLink - invalid asic number") return #loop through channels, check test pattern against data syncDataCounts = [{} for i in range(16)] #dict for each channel for ch in range(0,16,1): self.selectChannel(adcNum,ch, 1) time.sleep(0.05) data = self.femb.get_data(npackets) if data == None: continue for samp in data: if samp == None: continue #chNum = ((samp >> 12 ) & 0xF) sampVal = (samp & 0xFFF) if sampVal in syncDataCounts[ch]: syncDataCounts[ch][sampVal] += 1 else: syncDataCounts[ch][sampVal] = 1 # check jitter badSync = 0 maxCodes = [None]*16 syncDicts = [{}]*16 for ch in range(0,16,1): sampSum = 0 maxCode = None nMaxCode = 0 for code in syncDataCounts[ch]: nThisCode = syncDataCounts[ch][code] sampSum += nThisCode if nThisCode > nMaxCode: nMaxCode = nThisCode maxCode = code maxCodes[ch] = maxCode syncDicts[ch]["maxCode"] = maxCode syncDicts[ch]["nSamplesMaxCode"] = nMaxCode syncDicts[ch]["nSamples"] = sampSum syncDicts[ch]["zeroJitter"] = True if len(syncDataCounts[ch]) > 1: syncDicts[ch]["zeroJitter"] = False badSync = 1 diff = sampSum-nMaxCode frac = diff / float(sampSum) print("Sync Error: Jitter for Ch {:2}: {:8.4%} ({:5}/{:5})".format(ch,frac,diff,sampSum)) for ch in range(0,16,1): maxCode = maxCodes[ch] correctCode = self.ADC_TESTPATTERN[ch] syncDicts[ch]["data"] = True syncDicts[ch]["maxCodeMatchesExpected"] = True if maxCode is None: syncDicts[ch]["data"] = False badSync = 1 print("Sync Error: no data for ch {:2}".format(ch)) elif maxCode != correctCode: syncDicts[ch]["maxCodeMatchesExpected"] = True badSync = 1 print("Sync Error: mismatch for ch {:2}: expected {:#03x} observed {:#03x}".format(ch,correctCode,maxCode)) return badSync, syncDicts def selectChannel(self,asic,chan,hsmode=1,singlechannelmode=None): """ asic is chip number 0 to 7 chan is channel within asic from 0 to 15 hsmode: if 0 then streams all channels of a chip, if 1 only te selected channel. defaults to 1 singlechannelmode: not implemented """ hsmodeVal = int(hsmode) & 1; asicVal = int(asic) if (asicVal < 0 ) or (asicVal >= self.NASICS ) : print( "femb_config_femb : selectChan - invalid ASIC number, only 0 to {} allowed".format(self.NASICS-1)) return chVal = int(chan) if (chVal < 0 ) or (chVal > 15 ) : print("femb_config_femb : selectChan - invalid channel number, only 0 to 15 allowed") return #print( "Selecting ASIC " + str(asicVal) + ", channel " + str(chVal)) self.femb.write_reg ( self.REG_HS, hsmodeVal) regVal = (chVal << 8 ) + asicVal self.femb.write_reg( self.REG_SEL_CH, regVal) """ def testUnsyncNew(self, chip): print("\n FEMB_CONFIG --> testUnsyncNew() -> chip = {} --".format(chip)) adcNum = int(chip) if (adcNum < 0 ) or (adcNum > 3 ): print (" FEMB_CONFIG --> testUnsyncNew() -> Invalid asic number, must be between 0 and 3") return for j in range(100): #reset sync error self.femb.write_reg(11, 1) # ERROR_RESET <= reg11_p(0) time.sleep(0.01) self.femb.write_reg(11, 0) # ERROR_RESET <= reg11_p(0) time.sleep(0.01) if (chip == 0): conv_error = self.femb.read_reg(12) # reg12_i => x"" & CONV_ERROR header_error = self.femb.read_reg(13) # reg13_i => HDR2_ERROR & HDR1_ERROR # elif (chip == 1): # conv_error = self.femb.read_reg(50) # reg50_i => x"0000" & CONV_ERROR_1 # header_error = self.femb.read_reg(51) # reg51_i => HDR2_ERROR_2 & HDR1_ERROR_2 # elif (chip == 2): # conv_error = self.femb.read_reg(52) # header_error = self.femb.read_reg(53) # elif (chip == 3): # conv_error = self.femb.read_reg(54) # header_error = self.femb.read_reg(55) error = False if (conv_error != 0): # CONV_ERROR exists print (" FEMB_CONFIG --> testUnsyncNew() -> Convert error({})! Trial {}".format(hex(conv_error),j)) error = True else: print (" FEMB_CONFIG --> testUnsyncNew() -> No Convert Error ({}) Trial {}!".format(hex(conv_error),j)) #convert = 0 if (header_error != 0): # HEADER_ERROR exists print (" FEMB_CONFIG --> testUnsyncNew() -> Header error ({})!".format(hex(header_error))) error = True else: print (" FEMB_CONFIG --> testUnsyncNew() -> No Header Error({})! Trial {}".format(hex(header_error),j)) #not finding header if (error == False): #break loop if no error found print (" FEMB_CONFIG --> testUnsyncNew() -> Correct on Loop {} Trial {}".format(j,j)) break #return True elif (j > 30): print (" FEMB_CONFIG --> testUnsyncNew() -> Convert error({})! Trial {}".format(hex(conv_error),j)) print (" FEMB_CONFIG --> testUnsyncNew() -> Header error ({})! Trial {}".format(hex(header_error),j)) #sync_status = self.femb.read_reg(self.REG_ASIC_SPIPROG) >> 24 #print ("FEMB_CONFIG--> Register 2 Sync status is {}".format(hex(sync_status))) return False else: self.configAdcAsic(False) #print ("Loop {}".format(j)) for ch in range(0,16,1): for test in range(0,200,1): data = self.get_data_chipXchnX(chip = adcNum, chn = ch, packets = 1)#issue here? #print("unsyncNew data -> {}".format(data)) if (len(data) == 0): print (" FEMB_CONFIG--> testUnsyncNew() -> Sync response didn't come in") return False for samp in data[0:len(data)]: if samp != self.ADC_TESTPATTERN[ch]: print (" FEMB_CONFIG --> testUnsyncNew() -> Chip {} chn {} looking for {} but found {}".format( adcNum, ch, hex(self.ADC_TESTPATTERN[ch]), hex(samp))) return False return True """ def initFunctionGenerator(self): """ rm = visa.ResourceManager() try: #keysight = rm.open_resource('USB0::0x0957::0x5707::MY53802435::0::INSTR') keysight = rm.open_resource(u'USB0::2391::22279::MY53802422::0::INSTR') print ("Keysight Initialize--> Instrument Connected") except VisaIOError: print ("Keysight Initialize--> Exact system name not found") keysight = rm.open_resource(rm.list_resources()[0]) #Sets the self.instrument object in "GPIB_FUNCTIONS" to the #connected instrument, this makes it very easy to reference later time.sleep(0.1) keysight.write("Source1:Apply:Triangle {},{},{}".format(settings.frequency,settings.amplitude,settings.offset)) keysight.write("Output1:Load 50") #keysight.write("Output1:Load INFINITY") keysight.write("Source1:Burst:Mode Triggered") keysight.write("Source1:Burst:Ncycles 1") keysight.write("Source1:Burst:Phase {}".format(settings.phase_start)) keysight.write("Source1:Burst:State ON") keysight.write("Initiate1:Continuous OFF") return keysight """ def configAdcAsic(self): #cp 1/29/18 #helper """ config() """ print("FEMB_CONFIG -> configAdcAsic() --") Adcasic_regs = self.adc_reg.REGS #ADC ASIC SPI registers self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0x40) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) time.sleep(0.01) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0x20) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) time.sleep(0.01) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0x40) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) time.sleep(0.01) self.select_chn(1) # channel 1 & write clocks self.select_chn(3) # channel 3 & write clocks self.select_chn(1) # channel 1 & write clocks for k in range(10): i = 0 for regNum in range(self.REG_ADCSPI_BASE,self.REG_ADCSPI_BASE+len(Adcasic_regs),1): self.femb.write_reg( regNum, Adcasic_regs[i]) i = i + 1 # Program ADC ASIC SPI self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) time.sleep(.05) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 1) time.sleep(.05) self.femb.write_reg ( self.REG_ASIC_SPIPROG, 1) time.sleep(.05) #self.femb.write_reg ( self.REG_ASIC_SPIPROG, 0) # Check ADC ASIC SPI readback_regs = [] i = 0 for regNum in range(self.REG_ADCSPI_RDBACK_BASE,self.REG_ADCSPI_RDBACK_BASE+len(Adcasic_regs),1): readback_regs.append(self.femb.read_reg(regNum)) #print ( "femb_config_sbnd.py -> configAdcAsic() -> readback reg: " + str(hex(regNum)) + " from base: " + str(hex(Adcasic_regs[i]))) i = i + 1 i=0 for i in range (0,len(readback_regs),1): #Why is this reading out extra adc asic registers? if (Adcasic_regs[i] != readback_regs[i]): print ("\t FEMB_CONFIG --> CONFIG() ERROR -> configAdcAsic() -> Sent Adcasic_reg not correct = " + str(hex(Adcasic_regs[i])) + " , rb_reg = " + str(hex(readback_regs[i])) ) else: continue #print ("femb_config_sbnd.py -> configAdcAsic() -> Adcasic_reg correct = " + str(hex(Adcasic_regs[i])) + " , rb_reg = " + str(hex(readback_regs[i])) ) # val = self.femb.read_reg ( self.REG_ASIC_SPIPROG ) wrong = False # # if (((val & 0x10000) >> 16) != 1): # #print ("FEMB_CONFIG--> Something went wrong when programming ADC 1") # wrong = True # if (((val & 0x40000) >> 18) != 1): # #print ("FEMB_CONFIG--> Something went wrong when programming ADC 2") # wrong = True # if (((val & 0x100000) >> 20) != 1): # #print ("FEMB_CONFIG--> Something went wrong when programming ADC 3") # wrong = True # if (((val & 0x400000) >> 22) != 1): # #print ("FEMB_CONFIG--> Something went wrong when programming ADC 4") # wrong = True if (wrong == True and k == 9): print ("\tFEMB_CONFIG--> CONFIG() -> SPI_Status") print (hex(val)) sys.exit("\tFEMB_CONFIG--> CONFIG() -> femb_config_femb : Wrong readback. ADC SPI failed") return elif (wrong == 0): print ("\tFEMB_CONFIG--> CONFIG() -> ADC ASIC SPI is OK") break #else: #print ("FEMB_CONFIG--> Try {}, since SPI response was {}".format(k + 2, hex(val))) def FinalSyncCheck(self): # # FinalSyncCheck() # # procedures: # line 337: set chip [determine which chip is being sync'd] # line 339: set global register [send test data from PC to FPGA (where is this data going?) F5=1 # line 340: write SPI (wtf is SPI?) print ("FEMB_CONFIG--> Final sync check to make sure") for a in settings.chips_to_use: self.adc_reg.set_adc_global(chip = a, f5 = 1) self.configAdcAsic() self.select_chn(1) # channel 0 & write clocks self.select_chn(3) # channel 0 & write clocks self.select_chn(1) # channel 0 & write clocks # quad board settings: #self.select_chip(chip = a) # single board settings: #select_chip is not necessary badSync = 0 for ch in range(0,16,1): for test in range(0,100,1): data = self.get_data_chipXchnX(chip = a, chn = ch, packets = 1) if (len(data) == 0): print ("FEMB_CONFIG--> Sync response bad. Exiting...") return 1 for samp in data[0:len(data)]: if samp != self.ADC_TESTPATTERN[ch]: badSync = 1 print ("FEMB_CONFIG--> Chip {} chn {} looking for {} but found {}".format( a, ch, hex(self.ADC_TESTPATTERN[ch]), hex(samp))) if badSync == 1: break #print("time after checking the sample {}".format(time.time())) if badSync == 1: break #print("time after checking 100 samples {}".format(time.time())) if badSync == 1: self.femb.write_reg( 9, 1) sys.exit("FEMB_CONFIG--> Failed final check looking at channel test values") self.configAdcAsic() print ("FEMB_CONFIG--> Chip {} recieved the correct test values!".format(a)) resp = self.testUnsyncNew(a) if (resp == False): self.femb.write_reg(9, 1) sys.exit("FEMB_CONFIG--> Sync failed in the final check") self.adc_reg.set_adc_global(chip = a, f5 = 0) # for i in range (100): # sync_status = self.femb.read_reg(self.REG_ASIC_SPIPROG) >> 24 # if ((sync_status & 0x3F) != 0): # # if (i == 99): # print ("FEMB_CONFIG--> Register 2 giving back a sync error") # print ("Sync status is {}".format(hex(sync_status))) # sys.exit("Done with trying") # # self.configAdcAsic(False) # # else: # print ("FEMB_CONFIG--> No Sync error through Register 2 check: ({})!".format(hex(sync_status))) # break def fixUnsyncNew(self, adc): print("\n femb_config_sbnd.py -> fixUnsyncNew() -> adc = " + str(adc) + "\n") adcNum = int(adc) if (adcNum < 0) or (adcNum > 3): print ("FEMB_CONFIG--> femb_config_femb : testLink - invalid asic number") return initLATCH1_4 = self.femb.read_reg( settings.LATCHLOC_reg) initPHASE = self.femb.read_reg( settings.CLKPHASE_reg) #loop through sync parameters shiftMask = (0xFF << 8*adcNum) initSetting = (initLATCH1_4 & shiftMask) >> (8*adcNum) print ("FEMB_CONFIG--> First testing around default value of {}".format(initSetting)) for phase in range(0,4,1): clkMask = (0x3 << (adcNum * 2)) testPhase = ( (initPHASE & ~(clkMask)) | (phase << (adcNum * 2)) ) self.femb.write_reg( settings.CLKPHASE_reg, testPhase) #print ("Init Setting is {}".format(hex(initSetting))) #print ("Will test {}, {}, and {}".format(initSetting - 1, initSetting, initSetting + 1)) for shift in range(initSetting - 1,initSetting + 2,1): print ("\n\tfemb_config_sbnd.py -> fixUnsyncNew -> This time, we're testing {}\n".format(shift)) testShift = ( (initLATCH1_4 & ~(shiftMask)) | (shift << 8*adcNum) ) self.femb.write_reg( settings.LATCHLOC_reg, testShift) print ("FEMB_CONFIG--> Trying to sync Chip {} with Latch Lock:{} and Phase:{}".format(adcNum, hex(testShift), hex(testPhase))) #test link unsync = self.testUnsyncNew(adcNum) if unsync == True : print ("FEMB_CONFIG--> ADC {} synchronized".format(adc)) self.REG_LATCHLOC1_4_data = testShift self.REG_CLKPHASE_data = testPhase return True #Then try all settings print ("FEMB_CONFIG--> Now testing the rest of them") for phase in range(0,4,1): clkMask = (0x3 << (adcNum * 2)) testPhase = ( (initPHASE & ~(clkMask)) | (phase << (adcNum * 2)) ) self.femb.write_reg( settings.CLKPHASE_reg, testPhase) #First test latch lock settings close to default values shiftMask = (0xFF << 8*adcNum) initSetting = initLATCH1_4 & shiftMask for shift in range(0,16,1): testShift = ( (initLATCH1_4 & ~(shiftMask)) | (shift << 8*adcNum) ) self.femb.write_reg( settings.LATCHLOC_reg, testShift) print ("FEMB_CONFIG--> Trying to sync Chip {} with Latch Lock:{} and Phase:{}".format(adcNum, hex(testShift), hex(testPhase))) #test link unsync = self.testUnsyncNew(adcNum) if unsync == True : print ("FEMB_CONFIG--> ADC {} synchronized".format(adc)) self.REG_LATCHLOC1_4_data = testShift self.REG_CLKPHASE_data = testPhase return True #if program reaches here, sync has failed print ("FEMB_CONFIG--> ADC SYNC process failed for ADC # " + str(adc)) return False def select_chn(self, chn): """ % select_chn() % This function is used in sending instructions to fpga to select chip. % There is not an option to select a chip for single socket boards. % This function is mostly relevent for using on quad board. % This function is used to output the desired clock settings correlated to the % 'selected chip' % Assume 16 channels % % [quad board:] % clock reg values [10-43] % % [single board:] % clock reg values [21-33] """ print("\t FEMB_CONFIG//select_chn()") if (chn < 0 ) or (chn > settings.chn_num): print ("\t FEMB_CONFIG//select_chn()//Error: Chn must be between 0 and {}".format(self.chn_num)) return """ quad board remains... self.femb.write_reg(9, 1) # STOP_ADC <= reg9_p (quad board) time.sleep(0.01) # WAIT self.femb.write_reg(3, 0x80000001 + chip) # CHP_SELECT <= reg3_p(7 downto 0) (quad board) time.sleep(0.01) # WAIT self.femb.write_reg(9, 0) # STOP_ADC <= reg9_p (quad board) time.sleep(0.01) # WAIT self.femb.write_reg(47, 1) # ERROR_RESET <= reg47_p (quad board) time.sleep(0.01) # WAIT self.femb.write_reg(47, 0) # ERROR_RESET <= reg47_p (quad board) """ # STOP ADC: TRUE ??? time.sleep(0.01) # WAIT self.femb.write_reg(7, 0x00000001 + chn) # CHN_SELECT <= reg7(7 downto 0) time.sleep(0.01) # WAIT # STOP ADC: FALSE ??? # WAIT self.femb.write_reg(11, 1) # CHN_SELECT <= reg11(0) time.sleep(0.01) # WAIT self.femb.write_reg(11, 0) # CHN_SELECT <= reg11(0) self.selected_chn = chn # originally self.selected_chip?? what is it used for? if (self.femb.read_reg(7) != 0x00000001 + chn): print ("\t FEMB CONFIG --> select_chn() -> Error - chip not chosen correctly!") print ("\t Should be ".format(hex(0x00000001 + chn))) print ("\t It is {}".format(hex(self.femb.read_reg(7)))) to_add = 0 """ quad board remains... if (settings.extended == True): to_add = 4 self.femb.write_reg(10, settings.reg10_value[chip + to_add]) #INV_RST_ADC1 <= reg10_p(0) #INV_READ_ADC1<= reg10_p(1) #Course Control Quad Board self.femb.write_reg(11, settings.reg11_value[chip + to_add]) self.femb.write_reg(12, settings.reg12_value[chip + to_add]) self.femb.write_reg(13, settings.reg13_value[chip + to_add]) self.femb.write_reg(14, settings.reg14_value[chip + to_add]) self.femb.write_reg(15, settings.reg15_value[chip + to_add]) self.femb.write_reg(16, settings.reg16_value[chip + to_add]) #Fine Control Quad Board self.femb.write_reg(17, settings.reg17_value[chip + to_add]) self.femb.write_reg(18, settings.reg18_value[chip + to_add]) self.femb.write_reg(19, settings.reg19_value[chip + to_add]) self.femb.write_reg(19, settings.reg19_value[chip + to_add]) self.femb.write_reg(19, 0x80000000 + settings.reg19_value[chip + to_add]) """ self.femb.write_reg( settings.CLKPHASE_reg, 0xFF) self.femb.write_reg( settings.CLKPHASE_reg, self.REG_CLKPHASE_data) time.sleep(0.01) def get_data_chipXchnX(self, chip, chn, packets = 1): if (chn < -1 ) or (chn > settings.chn_num ): print ("FEMB CONFIG --> get_data_chipXchnX() -> Error: Channel must be between 0 and 15, or -1 for all channels") return if (chip < 0 ) or (chip > settings.chip_num ): print ("FEMB CONFIG --> get_data_chipXchnX() -> Error: Chip must be between 0 and {}".format(self.chip_num)) return k = 0 for i in range(10): data = self.femb.get_data_packets(data_type = "int", num = packets, header = False) try: if (k > 0): print ("FEMB CONFIG --> Now doing another test") print (hex(data[0])) print (data[0] == 0xFACE) print (data[0] != 0xFACE) if (data[0] != 0xFACE): #If FACE isn't the first 2 bytes, turn WIB mode off and then on and try again self.femb.write_reg(8,0) # Turn WIB Mode Off time.sleep(0.01) self.femb.write_reg(8,1) # Turn WIB Mode On time.sleep(0.01) # quad board settings: # self.select_chip(chip) #tells fpga which chip information to provide # self.femb.write_reg(3, chip+1) # CHP_Select <= reg_3p(7-0) # # CHN_Select <= reg_3p(15-0) # # WIB_Mode <= reg_3p(31) # single board settings: self.femb.write_reg(7, chn) # CHN_select <= reg7_p(7-0) time.sleep(0.001) if (k > 8): print ("FEMB CONFIG --> Error in get_data_chipXchnX: Packet format error") #print (hex(data[0])) #print (data) return None else: print ("FEMB CONFIG --> Error in get_data_chipXchnX: Packet format error, trying again...") print ("k = {}".format(k)) print (data[0:13]) print (hex(data[0])) print ("FEMB CONFIG --> Hey: {}".format(data[0] == 0xFACE)) k += 1 else: break except IndexError: print ("FEMB CONFIG --> Something was wrong with the incoming data") print (data) test_length = len(data) # if ((test_length % self.BPS) != 0): # print ("FEMB CONFIG -> Error in get_data_chipXchnX: Irregular packet size") # print (data) # return None full_samples = test_length // self.BPS chn_data = [] for i in range (full_samples): if (chn == 7): chn_data.append(data[(self.BPS*i)+1] & 0x0FFF) if (chn == 6): chn_data.append(((data[(self.BPS*i)+2] & 0x00FF) << 4) + ((data[(self.BPS*i)+1] & 0xF000) >> 12)) if (chn == 5): chn_data.append(((data[(self.BPS*i)+3] & 0x000F) << 8) + ((data[(self.BPS*i)+2] & 0xFF00) >> 8)) if (chn == 4): chn_data.append(((data[(self.BPS*i)+3] & 0xFFF0) >> 4)) if (chn == 3): chn_data.append(data[(self.BPS*i)+4] & 0x0FFF) if (chn == 2): chn_data.append(((data[(self.BPS*i)+5] & 0x00FF) << 4) + ((data[(self.BPS*i)+4] & 0xF000) >> 12)) if (chn == 1): chn_data.append(((data[(self.BPS*i)+6] & 0x000F) << 8) + ((data[(self.BPS*i)+5] & 0xFF00) >> 8)) if (chn == 0): chn_data.append(((data[(self.BPS*i)+6] & 0xFFF0) >> 4)) if (chn == 15): chn_data.append(data[(self.BPS*i)+7] & 0x0FFF) if (chn == 14): chn_data.append(((data[(self.BPS*i)+8] & 0x00FF) << 4) + ((data[(self.BPS*i)+7] & 0xF000) >> 12)) if (chn == 13): chn_data.append(((data[(self.BPS*i)+9] & 0x000F) << 8) + ((data[(self.BPS*i)+8] & 0xFF00) >> 8)) if (chn == 12): chn_data.append(((data[(self.BPS*i)+9] & 0xFFF0) >> 4)) if (chn == 11): chn_data.append(data[(self.BPS*i)+10] & 0x0FFF) if (chn == 10): chn_data.append(((data[(self.BPS*i)+11] & 0x00FF) << 4) + ((data[(self.BPS*i)+10] & 0xF000) >> 12)) if (chn == 9): chn_data.append(((data[(self.BPS*i)+12] & 0x000F) << 8) + ((data[(self.BPS*i)+11] & 0xFF00) >> 8)) if (chn == 8): chn_data.append(((data[(self.BPS*i)+12] & 0xFFF0) >> 4)) if (chn == -1): return (data) return chn_data
class FEMB_CONFIG: def __init__(self): self.NASICS = 4 #declare board specific registers self.REG_RESET = 0 self.REG_FEASIC_SPI = 5 self.REG_FESPI_BASE = 20 self.REG_FESPI_RDBACK_BASE = None self.REG_ADCSPI_RDBACK_BASE = None self.REG_HS = 17 self.REG_TEST_PULSE = 99 self.REG_TEST_PULSE_FREQ = 500 self.REG_TEST_PULSE_DLY = 80 self.REG_TEST_PULSE_AMPL = 0 % 32 self.REG_EN_CALI = 16 self.REG_RESET = 0 self.REG_DAC_VALUE = 1 self.REG_SET_DAC = 2 self.REG_START = 3 self.REG_SEL_ASIC = 4 self.REG_SEL_CH = 4 self.REG_ASIC_RESET = 5 self.REG_ASIC_SPIPROG = 5 self.REG_SAMPLE_STOP = 6 self.REG_TP_PERIOD_P = 7 self.REG_TP_PERIOD_N = 7 self.REG_TP_MODE = 9 self.REG_TST_SW = 12 self.REG_LED_CNTL = 13 self.REG_FESPI_BASE = 20 self.REG_FRAME_SIZE = 40 self.REG_DAC_ADC_EN = 60 self.REG_TST_SW = 12 self.plot = plot_functions() self.comm_settings = None #initialize FEMB UDP object self.femb = FEMB_UDP() self.fe_reg = FE_ASIC_REG_MAPPING() self.WIB_RESET = 1 self.BPS = 13 #Bytes per sample self.selected_chip = None self.selected_chn = None def resetFEMBBoard(self): print("FEMB_CONFIG--> Reset FEMB (4 seconds)") sys.stdout.flush() #Reset FEMB system self.femb.write_reg(self.REG_RESET, 1) time.sleep(4) print("FEMB_CONFIG--> Reset FEMB is DONE") def initBoard(self): print("FEMB_CONFIG--> Initialize FEMB") #set up default registers #Tells the FPGA to turn on the ASICs self.femb.write_reg(12, 0x0) #self.turnOnAsics() #added #Tells the FPGA to turn off each DAC self.femb.write_reg(61, 0xF) #Set to Regular Mode (as opposed to Sampling Scope mode) and pick a chip/channel output self.femb.write_reg(10, 0) self.select_chip_chn(chip=2, chn=7) #Select TP FE Mode self.femb.write_reg(9, 8) #Give a default DAC value self.femb.write_reg(1, settings.default_DAC) self.femb.write_reg(2, 1) self.femb.write_reg(2, 0) #Give a default pulse timing self.femb.write_reg(7, (settings.default_TP_Shift << 16) + settings.default_TP_Period) #Write the default ADC settings i = 0 for reg in range(65, 69, 1): self.femb.write_reg(reg, settings.Latch_Settings[i]) i = i + 1 i = 0 for reg in range(69, 73, 1): self.femb.write_reg(reg, settings.Phase_Settings[i]) i = i + 1 self.femb.write_reg(73, settings.test_ADC_Settings) self.femb.write_reg(74, settings.pre_buffer) #Write the frame size as a multiple of 16 frame_size = settings.frame_size if (frame_size % 16 != 0): frame_size = 16 * (frame_size // 16) #Write the defaul ASIC settings self.fe_reg.set_fe_board(sts=1, snc=1, sg=1, st=1, smn=0, sbf=1, slk=0, stb=0, s16=0, slkh=0, sdc=0, sdacsw2=1, sdacsw1=0, sdac=settings.sync_peak_height) print("FEMB_CONFIG --> FE ASIC SPI") self.configFeAsic() print("FEMB_CONFIG--> Initialize FEMB is DONE") def turnOffAsics(self): self.femb.write_reg(self.REG_TST_SW, 0xF) #pause after turning off ASICs time.sleep(2) def turnOnAsic(self, asic): asicVal = int(asic) if (asicVal < 0) or (asicVal >= self.NASICS): print( "femb_config_femb : turnOnAsics - invalid ASIC number, only 0 to {} allowed" .format(self.NASICS - 1)) return print("turnOnAsic " + str(asicVal)) #self.femb.write_reg( self.REG_TST_SW, 0xF) #turn off all self.femb.write_reg_bits(self.REG_TST_SW, asicVal, 0x1, 0x0) time.sleep(2) #pause after turn on #start ASICs self.femb.write_reg(self.REG_START, 1) self.configFeAsic() def turnOnAsics(self): #print( "Turn On Asics" ) #self.femb.write_reg( self.REG_TST_SW, 0x0) #time.sleep(1) #pause after turn on #start ASICs #self.femb.write_reg( self.REG_START, 1) #self.configFeAsic() self.turnOnAsic(0) self.turnOnAsic(1) self.turnOnAsic(2) self.turnOnAsic(3) #pause after turning on ASICs time.sleep(2) def configFeAsic(self, to_print=False): #Grab ASIC settings from linked class Feasic_regs = self.fe_reg.REGS #Choose to output status updates or not if (to_print == True): print("FEMB_CONFIG--> Config FE ASIC SPI") #Try 10 times (ocassionally it wont work the first time) for k in range(10): i = 0 for regNum in range(self.REG_FESPI_BASE, self.REG_FESPI_BASE + len(Feasic_regs), 1): self.femb.write_reg(regNum, Feasic_regs[i]) # print (hex(Feasic_regs[i])) i = i + 1 #Write ADC ASIC SPI if (to_print == True): print("FEMB_CONFIG--> Program FE ASIC SPI") #Reset, then write twice self.femb.write_reg(self.REG_FEASIC_SPI, 2) self.femb.write_reg(self.REG_FEASIC_SPI, 0) time.sleep(.2) self.femb.write_reg(self.REG_FEASIC_SPI, 1) self.femb.write_reg(self.REG_FEASIC_SPI, 0) time.sleep(.2) self.femb.write_reg(self.REG_FEASIC_SPI, 1) self.femb.write_reg(self.REG_FEASIC_SPI, 0) time.sleep(.2) if (to_print == True): print("FEMB_CONFIG--> Check FE ASIC SPI") #The FPGA automatically compares the readback to check if it matches what was written. That result is read back #A bit that's zero means the corresponding ASIC didn't write properly val = self.femb.read_reg(self.REG_FEASIC_SPI) wrong = False if (((val & 0x10000) >> 16) != 1 and (0 in settings.chips_to_use)): print( "FEMB_CONFIG--> Something went wrong when programming FE 1" ) wrong = True if (((val & 0x20000) >> 17) != 1 and (1 in settings.chips_to_use)): print( "FEMB_CONFIG--> Something went wrong when programming FE 2" ) wrong = True if (((val & 0x40000) >> 18) != 1 and (2 in settings.chips_to_use)): print( "FEMB_CONFIG--> Something went wrong when programming FE 3" ) wrong = True if (((val & 0x80000) >> 19) != 1 and (3 in settings.chips_to_use)): print( "FEMB_CONFIG--> Something went wrong when programming FE 4" ) wrong = True if (wrong == True and k == 9): print("FEMB_CONFIG--> SPI_Status is {}").format(hex(val)) #sys.exit("FEMB_CONFIG--> femb_config_femb : Wrong readback. FE SPI failed") return elif (wrong == False): self.fe_reg.info.fe_regs_sent = Feasic_regs if (to_print == True): print("FEMB_CONFIG--> FE ASIC SPI is OK") break #ASSUMES ASICS HAVE BEEN SET FOR THE INTERNAL PULSER def syncADC(self, chips): print("FEMB_CONFIG--> Start sync ADC") #Don't ask me why, but you need to set the channel at this point for it to output the right data self.select_chip_chn(chip=0, chn=1) for chip in chips: #Tells the FPGA to turn on each DAC self.femb.write_reg(61, 0x0) #Read from DATA output ADCs self.femb.write_reg(60, 0) #Set to Regular Mode (not sampling scope mode) self.femb.write_reg(10, 0) #Select the internal DAC readout self.femb.write_reg(9, 3) #Get the ASIC to send out pulses. Bit 6 needs to be high for ASIC DAC self.reg_17_value = (settings.default_TP_Period << 16) + ( settings.default_TP_Shift << 8) + (0b01000000) self.femb.write_reg(17, self.reg_17_value) print("FEMB_CONFIG--> Test ADC {}".format(chip)) for chn in range(settings.channels): #Tests if it's synchronized, returns True if it is unsync = self.testUnsync(chip=chip, chn=chn) if unsync != True: print( "FEMB_CONFIG--> Chip {}, Chn {} not synced, try to fix" .format(chip, chn)) response = self.fixUnsync_outputADC(chip=chip, chn=chn) if (response != True): print( "FEMB_CONFIG--> Something is wrong with Chip {}, Chn {}" .format(chip, chn)) # sys.exit ("FEMB_CONFIG--> ADC {} could not sync".format(chip)) print("FEMB_CONFIG--> ADC {} synced!".format(chip)) print("FEMB_CONFIG--> Trying to sync test ADC".format(chip)) #Have one of the channels output its pulse to the test monitor pin self.fe_reg.set_fe_chn(chip=chip, chn=0, smn=1) self.configFeAsic() #Read from TEST output ADCs self.femb.write_reg(60, 1) #Select the monitor readout self.femb.write_reg(9, 3) unsync = self.testUnsync(chip=chip, chn=chn) if unsync != True: print( "FEMB_CONFIG--> Chip {} (test ADC) not synced, try to fix". format(chip)) response = self.fixUnsync_testADC(chip=chip) if (response != True): print( "FEMB_CONFIG--> Something is wrong with Chip {} (test ADC)" .format(chip)) else: print("FEMB_CONFIG--> Chip {} (test ADC) synced!".format(chip)) self.comm_settings = [] print("FEMB_CONFIG--> Final Shift Settings: ") for reg in range(65, 69, 1): value = self.femb.read_reg(reg) print("Register {}: {}".format(reg, hex(value))) self.comm_settings.append(value) print("FEMB_CONFIG--> Final Phase Settings: ") for reg in range(69, 73, 1): value = self.femb.read_reg(reg) print("Register {}: {}".format(reg, hex(value))) self.comm_settings.append(value) value = self.femb.read_reg(73) print("Register {}: {}".format(73, hex(value))) self.comm_settings.append(value) self.femb.write_reg(17, 0) print("FEMB_CONFIG--> ADC passed Sync Test!") def testUnsync(self, chip, chn): #Get some packets of data self.select_chip_chn(chip=chip, chn=chn) data = self.get_data_chipXchnX(chip=chip, chn=chn, packets=25, data_format="counts") #Find some peaks peaks_index = detect_peaks(x=data, mph=settings.sync_peak_min, mpd=100) #Make sure you have more than 0 peaks (so it's not flat) and less than the maximum #(if there's no peak, the baseline will give hundreds of peaks) #If it's bad, print it, so we see (must enable inline printing for iPython) if (len(peaks_index) == 0) or (len(peaks_index) > settings.sync_peaks_max): print("Chip {}, Channel {} has {} peaks!".format( chip, chn, len(peaks_index))) # print (peaks_index) figure_data = self.plot.quickPlot(data) ax = figure_data[0] for j in peaks_index: y_value = data[j] ax.scatter(j / 2, y_value, marker='x') ax.set_ylabel('mV') ax.set_title("Error") ax.title.set_fontsize(30) for item in ([ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() + ax.get_yticklabels()): item.set_fontsize(20) plt.show() plt.close() return False #So that function before only gives you the X locations of where the peaks are. Let's get the Y values from that peaks_value = [] for i in peaks_index: peaks_value.append(data[i]) # print ("Chip {}, Channel {} has peak values {}".format(chip, chn, peaks_value)) #Check if the peak is at the wrong height (happens when it's not synced, the peak will be havled or doubled) for peak in peaks_value: if ((peak < settings.sync_peak_min) or (peak > settings.sync_peak_max)): print("FEMB CONFIG--> Chip {}, Chn {} has a peak that's {}". format(chip, chn, peak)) figure_data = self.plot.quickPlot(data) ax = figure_data[0] for j in peaks_index: y_value = data[j] ax.scatter(j / 2, y_value, marker='x') ax.set_ylabel('mV') ax.set_title("Error") ax.title.set_fontsize(30) for item in ([ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() + ax.get_yticklabels()): item.set_fontsize(20) plt.show() plt.close() return False #Check if the baseline is right (this also gets halved and doubled with unsynced ADCs) (avoid the peak to grab a middle section) try: baseline_area_start = peaks_index[0] + 200 baseline_area_end = peaks_index[1] - 200 except IndexError: baseline_area_start = 100 baseline_area_end = 500 baseline_data = data[baseline_area_start:baseline_area_end] baseline = np.mean(baseline_data) if ((baseline < settings.sync_baseline_min) or (baseline > settings.sync_baseline_max)): print("FEMB CONFIG--> Chip {}, Chn {} has a baseline that's {}". format(chip, chn, baseline)) figure_data = self.plot.quickPlot(data) ax = figure_data[0] for j in peaks_index: y_value = data[j] ax.scatter(j / 2, y_value, marker='x') ax.set_ylabel('mV') ax.set_title("Error") ax.title.set_fontsize(30) for item in ([ax.xaxis.label, ax.yaxis.label] + ax.get_xticklabels() + ax.get_yticklabels()): item.set_fontsize(20) plt.show() plt.close() return False return True #Shifts through all possible delay and phase options, checking to see if each one fixed the issue def fixUnsync_outputADC(self, chip, chn): self.select_chip_chn(chip=chip, chn=chn) shift_reg = chip + 65 phase_reg = chip + 69 #Get the initial setting you don't disturb the other channels init_shift = self.femb.read_reg(shift_reg) init_phase = self.femb.read_reg(phase_reg) #Because Python can't have a friggin NAND or XOR function that works right at the bitwise level, this is how we get the bitmask #This will find the 2 bits in the register that correspond to the channel you want to change. Say it's channel 2 #In binary, it makes 0b00000000000000000000000000110000 #Then inverts it to 0b11111111111111111111111111001111 #Now you AND that with the initial result to get the initial values WITHOUT the channel you want to change #Now you can bitshift your desired setting to that empty space with zeroes, like say you wanted to write a 0b10, #It would be 0b100000. Then add that to whatever the result of the initial values AND mask was. Boom, you've done it. init_mask = (0x3 << (2 * chn)) neg_mask = 0 for i in range(32): FF_bit = (0xFFFFFFFF >> i) & 0x1 test_bit = (init_mask >> i) & 0x1 if (FF_bit != test_bit): result_bit = 1 else: result_bit = 0 neg_mask = neg_mask + (result_bit << i) #There are 16 possible sync permutations for every ADC for shift in range(4): for phase in range(4): shift_setting = shift << (2 * chn) init_shift_with_mask = init_shift & neg_mask final_shift = shift_setting + init_shift_with_mask # print ("Shift is {}".format(shift)) # print ("phase is {}".format(phase)) # print ("Negative mask is {}".format(bin(neg_mask))) # print ("Initial reading is {}".format(bin(init_shift))) # print ("The new setting is {}".format(bin(shift_setting))) # print ("Making space for the new setting is {}".format(bin(init_shift_with_mask))) # print ("Adding together is {}".format(bin(final_shift))) self.femb.write_reg(shift_reg, final_shift) phase_setting = phase << (2 * chn) init_phase_with_mask = init_phase & neg_mask final_phase = phase_setting + init_phase_with_mask self.femb.write_reg(phase_reg, final_phase) #See if this new setting fixed it unsync = self.testUnsync(chip=chip, chn=chn) if unsync == True: print("FEMB_CONFIG--> Chip {}, Chn {} fixed!".format( chip, chn)) return True print("FEMB_CONFIG--> ADC SYNC process failed for Chip {}, Channel {}". format(chip, chn)) self.femb.write_reg(shift_reg, init_shift) self.femb.write_reg(phase_reg, init_phase) return False #Same thing as above, except the timing register is different, so the bitmath has to be changed. def fixUnsync_testADC(self, chip): self.select_chip_chn(chip=chip, chn=2) init_mask = (0xF << (2 * chip)) neg_mask = 0 for i in range(32): FF_bit = (0xFFFFFFFF >> i) & 0x1 test_bit = (init_mask >> i) & 0x1 if (FF_bit != test_bit): result_bit = 1 else: result_bit = 0 neg_mask = neg_mask + (result_bit << i) init_shift = self.femb.read_reg(73) print("Init shift is {}".format(hex(init_shift))) print("Init mask is {}".format(bin(init_mask))) print("Negative mask is {}".format(bin(neg_mask))) for shift in range(4): for phase in range(4): setting = (phase << 2) + shift print("Setting is {}".format(bin(setting))) final_setting = setting << (chip * 4) print("Final Setting is {}".format(bin(setting))) init_shift_with_mask = init_shift & neg_mask print("Initshift with mask is {}".format( hex(init_shift_with_mask))) really_final = init_shift_with_mask + final_setting print("Final setting to write is {}".format(bin(really_final))) # init_shift_with_mask = init_shift & neg_mask # final_shift = shift_setting + init_shift_with_mask # print ("Shift is {}".format(shift)) # print ("phase is {}".format(phase)) # print ("Negative mask is {}".format(bin(neg_mask))) # print ("Initial reading is {}".format(bin(init_shift))) # print ("The new setting is {}".format(bin(shift_setting))) # print ("Making space for the new setting is {}".format(bin(init_shift_with_mask))) # print ("Adding together is {}".format(bin(final_shift))) unsync = self.testUnsync(chip=chip, chn=1) if unsync == True: print( "FEMB_CONFIG--> Chip {} test ADC fixed!".format(chip)) return True print("FEMB_CONFIG--> ADC SYNC process failed for Chip {} ADC".format( chip)) return False #Select the chip and channel and read it out. And check that it was actually set. It's weirdly a problem def select_chip_chn(self, chip, chn): if (chip < 0) or (chip > settings.chip_num): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Chip must be between 0 and {}" .format(settings.chip_num)) return if (chn < 0) or (chn > 15): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Channel must be between 0 and 15" ) return chip_int = int(chip + 1) chn_int = int(chn) reg4_value = chn_int + (chip_int << 8) for i in range(10): self.femb.write_reg(4, reg4_value) time.sleep(0.1) reg4_read = self.femb.read_reg(4) try: if ((reg4_read & 0xF) != chn) or (( (reg4_read >> 8) & 0xF) != chip + 1): if (i == 9): sys.exit( "FEMB CONFIG--> Register response was {}, should have been {}, trying again..." .format(hex(reg4_read), hex(reg4_value))) else: print( "FEMB CONFIG--> Register response was {}, should have been {}, trying again..." .format(hex(reg4_read), hex(reg4_value))) else: self.selected_chip = chip self.selected_chn = chn break except TypeError: print("FEMB CONFIG--> No readback value, trying again...") #Get data in a variety of ways. You can even pre-convert it to mV! def get_data_chipXchnX(self, chip, chn, packets=1, data_format="counts"): if (chn < -1) or (chn > 15): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Channel must be between 0 and 15, or -1 for all channels" ) return if (chip < 0) or (chip > settings.chip_num): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Chip must be between 0 and {}, but it's {}" .format(settings.chip_num, chip)) return if (self.selected_chip != chip) or (self.selected_chn != chn): self.select_chip_chn(chip=chip, chn=chn) if (data_format == "bin"): data = self.femb.get_data_packets(data_type="bin", num=packets, header=True) data = self.femb.get_data_packets(data_type="int", num=packets, header=False) if (data_format == "mV"): for i in range(len(data)): data[i] = data[i] * (0.0018 / 16384) elif (data_format == "V"): for i in range(len(data)): data[i] = data[i] * (1.8 / 16384) return data #Get a whole chip's worth of data def get_data_chipX(self, chip, packets=1, data_format="counts"): chip_data = [ chip, [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [] ] for chn in range(16): for i in range(packets): chip_data[chn + 1].extend( list( self.get_data_chipXchnX(chip, chn, packets=1, data_format=data_format)[1:])) return chip_data #Placeholder for the full chip readout def get_data_chipXchnX_SS(self, chip, chn, packets=1): if (chn < -1) or (chn > 15): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Channel must be between 0 and 15, or -1 for all channels" ) return if (chip < 0) or (chip > settings.chip_num): print( "FEMB CONFIG -> Error in get_data_chipXchnX: Chip must be between 0 and {}, but it's {}" .format(settings.chip_num, chip)) return if (self.selected_chip != chip) or (self.selected_chn != chn): self.select_chip(chip=chip, chn=chn) k = 0 for i in range(10): data = self.femb.get_data_packets(data_type="int", num=packets, header=False) try: if (k > 0): print("FEMB CONFIG --> Now doing another test") print(hex(data[0])) print(data[0] == 0xFACE) print(data[0] != 0xFACE) if (data[0] != 0xFACE): #If FACE isn't the first 2 bytes, do the equivalent of turning WIB mode off and then on and try again self.femb.write_reg(3, chip + 1) self.select_chip(chip) if (k > 8): print( "FEMB CONFIG --> Error in get_data_chipXchnX: Packet format error" ) print(hex(data[0])) print(data) return None else: print( "FEMB CONFIG --> Error in get_data_chipXchnX: Packet format error, trying again..." ) print("k = {}".format(k)) print(data[0:13]) print(hex(data[0])) print(data[0] == 0xFACE) k += 1 else: break except IndexError: print( "FEMB CONFIG --> Something was wrong with the incoming data" ) print(data) test_length = len(data) # if ((test_length % self.BPS) != 0): # print ("FEMB CONFIG -> Error in get_data_chipXchnX: Irregular packet size") # print (data) # return None full_samples = test_length // self.BPS chn_data = [] for i in range(full_samples): if (chn == 7): chn_data.append(data[(self.BPS * i) + 1] & 0x0FFF) if (chn == 6): chn_data.append(((data[(self.BPS * i) + 2] & 0x00FF) << 4) + ((data[(self.BPS * i) + 1] & 0xF000) >> 12)) if (chn == 5): chn_data.append(((data[(self.BPS * i) + 3] & 0x000F) << 8) + ((data[(self.BPS * i) + 2] & 0xFF00) >> 8)) if (chn == 4): chn_data.append(((data[(self.BPS * i) + 3] & 0xFFF0) >> 4)) if (chn == 3): chn_data.append(data[(self.BPS * i) + 4] & 0x0FFF) if (chn == 2): chn_data.append(((data[(self.BPS * i) + 5] & 0x00FF) << 4) + ((data[(self.BPS * i) + 4] & 0xF000) >> 12)) if (chn == 1): chn_data.append(((data[(self.BPS * i) + 6] & 0x000F) << 8) + ((data[(self.BPS * i) + 5] & 0xFF00) >> 8)) if (chn == 0): chn_data.append(((data[(self.BPS * i) + 6] & 0xFFF0) >> 4)) if (chn == 15): chn_data.append(data[(self.BPS * i) + 7] & 0x0FFF) if (chn == 14): chn_data.append(((data[(self.BPS * i) + 8] & 0x00FF) << 4) + ((data[(self.BPS * i) + 7] & 0xF000) >> 12)) if (chn == 13): chn_data.append(((data[(self.BPS * i) + 9] & 0x000F) << 8) + ((data[(self.BPS * i) + 8] & 0xFF00) >> 8)) if (chn == 12): chn_data.append(((data[(self.BPS * i) + 9] & 0xFFF0) >> 4)) if (chn == 11): chn_data.append(data[(self.BPS * i) + 10] & 0x0FFF) if (chn == 10): chn_data.append(((data[(self.BPS * i) + 11] & 0x00FF) << 4) + ((data[(self.BPS * i) + 10] & 0xF000) >> 12)) if (chn == 9): chn_data.append(((data[(self.BPS * i) + 12] & 0x000F) << 8) + ((data[(self.BPS * i) + 11] & 0xFF00) >> 8)) if (chn == 8): chn_data.append(((data[(self.BPS * i) + 12] & 0xFFF0) >> 4)) if (chn == -1): return (data) return chn_data
class WRITE_DATA(object): def __init__(self, filedir="data"): self.femb = FEMB_UDP() self.filename = "output_write_data.bin" self.numpacketsrecord = 100 self.run = 0 self.runtype = 0 self.runversion = 0 self.date = int(datetime.datetime.today().strftime('%Y%m%d%H%M%S')) self.filedir = filedir @property def data_file_path(self): return os.path.join(self.filedir, self.filename) def assure_filedir(self): #check local directory structure if os.path.isdir(str(self.filedir)) == False: print("write_data: Data directory not found, making now.") os.makedirs(str(self.filedir)) #check if directory actually created if os.path.isdir(str(self.filedir)) == False: print( "write_data: Error creating data directory, check filesystem.") return None return 1 def open_file(self): print("write_data: Open file: %s" % self.data_file_path) self.assure_filedir() self.data_file = open(self.data_file_path, 'wb') return 1 def record_data(self, subrun, asic, asicCh): subrunVal = int(subrun) if subrunVal < 0: return asicVal = int(asic) if asicVal < 0: return asicChVal = int(asicCh) if asicChVal < 0: return #print("write_data: Record data") data = self.femb.get_data_packets(self.numpacketsrecord) if data == None: print( "write_data: Did not get any data, streaming might have failed!!!" ) return for packet in data: #UDP packet header self.data_file.write(struct.pack('!H', 0x0)) self.data_file.write(struct.pack('!H', 0xDEAD)) self.data_file.write(struct.pack('!H', 0xBEEF)) self.data_file.write(struct.pack('!H', 0x0)) self.data_file.write(struct.pack('!H', 0xBA5E)) self.data_file.write(struct.pack('!H', subrunVal)) self.data_file.write(struct.pack('!H', asicVal)) self.data_file.write(struct.pack('!H', asicChVal)) #write data self.data_file.write(packet) def close_file(self): print("write_data: Close file") self.data_file.close()