#!/usr/bin/python """ pll_status.py -- module to display pll status Author JPC : 02/10/2018 Eric Jules: 01/12/2018, adapt for Belle II """ import time import os import subprocess import sys import pathtocomponents import curses from fpga_comp import Arria10 from si534x_comp import Si534x from xcvr_comp import xcvr from eepromat24c_comp import EepromAT24C import addresses_comp as const def pll_window(pll, device, fpga, freq, conf, win): # SI5345_1 monitoring # inputs line = 2 for j in range(0, 2): #was 4 status, loss_of_signal = pll.read_loss_of_signal(j) if conf[j] != "Not used": win.addstr(line, 1, "Input " + str(j) + " : ",curses.A_BOLD) if loss_of_signal == True: win.addstr(line, 12,"Loss of signal ", RED) else: win.addstr(line, 12,"Input clock present", GREEN) status, oof = pll.read_out_of_frequency(j) # if oof == True: # win.addstr(line + 1, 12,"Out of frequency ", RED) #else: # win.addstr(line + 1, 12,"Nominal frequency ", GREEN) status, loss_of_signal_flg = pll.read_loss_of_signal_flg(j) if loss_of_signal_flg == True: win.addstr(line, 32, "LOS seen ", RED) else: win.addstr(line, 32, "No LOS since " + str(round(time.time() - start_time, 1)) + " seconds", GREEN) status, oof_flg = pll.read_out_of_frequency_flg(j) # if oof_flg == True: # win.addstr(line + 1, 32,"OOF seen ", RED) #else: # win.addstr(line + 1, 32, "No OOF since " + str(round(time.time() - start_time, 1)) + " seconds", GREEN) # win.addstr(" "+conf[j]) # line = line + 2 #else: #win.addstr(" Not used") # line = line + 1 # Measure frequencies # line = line + 1 # for port in freq.keys(): # status, frequency_read = fpga.read_pll_port_frequency(device, port) #win.addstr(11 + line, 1, "Port = " + str(port) + " : " + str(frequency_read), WHITE) # win.addstr(line, 1, "Output "+ str(port)+ " : ",curses.A_BOLD) # win.addstr(str(frequency_read)+" Hz (" + freq[port] +")") # line = line +1 # internal state machine #line = line + 1 #status, val = pll.read_run_mode() #win.addstr(line, 1, "PLL mode : ", curses.A_BOLD) #if val == "Normal": # win.addstr(val, GREEN) #else: # win.addstr(val, RED) # check lock line = line + 1 status, val = pll.read_loss_of_lock() win.addstr(line, 1, "PLL status: ", curses.A_BOLD) if val == True: win.addstr("Loss of lock", RED) else: win.addstr("Locked", GREEN) # check sticky bit status, val = pll.read_loss_of_lock_flg() if val == True: win.addstr(line, 32, "LOL seen", RED) else: win.addstr(line, 32, "No LOL since " + str(round(time.time() - start_time, 1)) + " seconds", GREEN) win.refresh() # Read masks values # y_max, x_max = win.getmaxyx() # line = 8 # col = x_max / 3 # win.addstr(line, col, "INTR flag values:",curses.A_BOLD) # line = line + 1 # masks = pll.read_mask_values() # for mask in sorted(masks.keys()): # win.addstr(line, col, mask + " : " + str(masks[mask])) # line = line + 1 # if line == y_max - 1: # line = 8 # col = col + x_max / 3 win.refresh() def fanout_window(fpga, win): status, frequency_read = fpga.read_pll_port_frequency("SI5340", 0) win.addstr(2, 1, "Face plate clock : ",curses.A_BOLD) if frequency_read < 127000000 or frequency_read > 128000000: win.addstr(str(frequency_read/1000)+" kHz", RED) win.addstr(" Warning : frequency out of range", YELLOW) else: win.addstr(str(frequency_read) + " Hz", GREEN) win.addstr(3,1,'Run number : ' , curses.A_BOLD) win.addstr(3,14,'{0:4d}'.format(fpga.runNumber()),GREEN) win.addstr(3,19,'Trigger tag : ' , curses.A_BOLD ) win.addstr(3,33, '{0:10d}'.format(fpga.triggerTag()) , GREEN ) win.addstr(3,44, 'Clock Up : ' , curses.A_BOLD ) if fpga.clockUp() == 1: win.addstr(3,55, 'OK' , GREEN ) else: win.addstr(3,55,'NO',RED) win.addstr(3,58, 'TTD Up : ' , curses.A_BOLD ) if fpga.ttdUp() == 1: win.addstr(3,67, 'OK' , GREEN ) else: win.addstr(3,67,'NO',RED) win.addstr(3,70,'Trigger type : ' , curses.A_BOLD) win.addstr(3,85,'{0:2d}'.format(fpga.triggerType()),GREEN) win.addstr(4,1,'Trigger counter : ' , curses.A_BOLD) win.addstr(4,19,'{0:5d}'.format(fpga.triggerCounter()),GREEN) win.addstr(5,1,'RX ready : ' , curses.A_BOLD) for link in range( 6 ): if fpga.validChannel( link ) == 0: win.addstr(5,12+3*link, 'XX' , CYAN ) elif fpga.rxReadyIndividual(link) == 1: win.addstr(5,12+3*link, 'OK' , GREEN ) else: win.addstr(5,12+3*link,'NO',RED) win.addstr(5,31,'TX ready : ' , curses.A_BOLD) for link in range( 6 ): if fpga.validChannel( link ) == 0: win.addstr(5,42+3*link, 'XX' , CYAN ) elif fpga.txReadyIndividual(link) == 1: win.addstr(5,42+3*link, 'OK' , GREEN ) else: win.addstr(5,42+3*link,'NO',RED) win.addstr(5,62,'b2link ready : ' , curses.A_BOLD) for link in range( 6 ): if fpga.validChannel( link ) == 0: win.addstr(5,77+3*link, 'XX' , CYAN ) elif fpga.b2linkReadyIndividual( link ) == 1: win.addstr(5,77+3*link, 'OK' , GREEN ) else: win.addstr(5,77+3*link,'NO',RED) win.refresh() def program_plls(plls, devices, files, win): #win.move(2,1) win.clrtobot() win.box() line = 4 for i in plls.keys(): # programs the 3 PLLs (status, part_number) = plls[i].read_part_number() (status, revision) = plls[i].read_device_revision() win.addstr(line, 1, "===== Hard resetting PLL "+str(devices[i])+" =====") plls[i].hard_reset() win.addstr(line , 1, "..... Done ...................................................") win.addstr(line , 1, "===== Programming PLL "+str(devices[i])+"======================") #win.addstr(line + 3, 1, "..... Configuration file is " + files[i]) #win.addstr(line + 4, 1, "..... Part number detected is : " + hex(part_number)) #win.addstr(line + 5, 1, "..... Device revision detected is : Rev. " + revision) win.refresh() plls[i].si534x_programming(files[i]) win.addstr(line , 1, "..... Done ...................................................") for input in range(0, 4): plls[i].enable_los(input) plls[i].enable_oof(input) win.refresh() line = line win.addstr(line, 1, "..... wait to stabilize ..................................") win.refresh() time.sleep(7) win.addstr(line, 1, "..... ready ..............................................") line = 32 for i in plls.keys(): plls[i].clear_lol_flg_bit() plls[i].clear_los_oof_flg_reg() # dic = plls[i].clear_los_oof_flg_reg() # for mes in dic: # win.addstr(line, 1, mes + dic[mes]) # line = line + 1 start_time = time.time() win.refresh() def draw_menu(stdscr, dev): os.chdir("../Python/components") # Creates xcvr object trans = xcvr(dev) # Creates Arria10 object fpga = Arria10(dev) # Creates pll objects pll_si5345_1 = Si534x(dev, 1, 0x68) pll_si5345_2 = Si534x(dev, 2, 0x68) pll_si5344 = Si534x(dev, 3, 0x68) plls = \ {1: pll_si5345_1, 2: pll_si5345_2, 3: pll_si5344 } devices = \ {1: "SI5345_U23", 2: "SI5345_U48", 3: "SI5344_U54" } ### Files for configuration for FTSW clock files1b = \ {1: "../data/Si5345-1-BII_FTSW-Registers.txt", 2: "../data/Si5345-2-BII_FTSW-Registers.txt", 3: "../data/Si5344-BII_FTSW-Registers.txt" } conf1 = \ {1: ["Expected frequency = 127.216 MHz", "Not used", "Not used", "Not used"], 2: ["Expected frequency = 127.216 MHz", "Not used", "Not used", "Not used"], 3: ["Expected frequency = 127.216 MHz", "Not used", "Not used", "Not used"] } # Modif EJ EP 17-01-2019 changement 2 premiers fichiers programmation pll ### Files for configuration for oscillator clock files2b = \ {1: "../data/Si5345-1-BII_FPGA-Registers.txt", 2: "../data/Si5345-2-BII_FPGA-Registers.txt", 3: "../data/Si5344-BII_OSCI-Registers.txt" } # Modif EJ EP 17-01-2019 changement 2 premiers fichiers programmation pll conf2 = \ {1: ["Not used", "Expected frequency = 127.216 MHz", "Not used", "Not used"], 2: ["Not used", "Expected frequency = 127.216 MHz", "Not used", "Not used"], 3: ["Expected frequency = 127.216 MHz", "Not used", "Not used", "Not used"] } freq = \ {1: { 0: "gbt_refclk0", 1: "gbt_refclk1", 2: "gbt_refclk2", 3: "gbt_refclk3"}, 2: { 0: "gbt_refclk4", 1: "gbt_refclk5", 3: "gbt_refclk6", 4: "gbt_refclk7", 8: "sys_clk_240"}, 3: { 0: "tfc_refclk", 1: "sys_clk_240"} } # Choose default pll files files = files1b conf = conf1 k = 0 global start_time start_time = time.time() #curses.resizeterm(61, 200) # Clear and refresh the screen for a blank canvas stdscr.clear() stdscr.refresh() # Start colors in curses curses.start_color() curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(4, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK) global WHITE global CYAN global RED global GREEN global YELLOW WHITE = curses.color_pair(1) CYAN = curses.color_pair(2) RED = curses.color_pair(3) GREEN = curses.color_pair(4) YELLOW = curses.color_pair(5) # define 4 windows proportional to max screen size y_max, x_max = stdscr.getmaxyx() win1 = stdscr.subwin(y_max/6, x_max-2, 0, 0) win1.box() win1.addstr(1, 1, "Command window", CYAN | curses.A_BOLD) board = EepromAT24C(dev, const.EEPROM_FPGA_BUS, const.EEPROM_U64_ADD) val = board.read_identification() val = val.split(":")[4] val = val.replace("\"","") val = val.split(",")[0] win1.addstr(" Running on : " + val, CYAN | curses.A_BOLD) #try: vers = fpga.read_version() #except ValueError: #vers = { "design_version": "N/A" , "server" : "N/A" , "links" : "N/A" } if not "server" in vers.keys(): vers["server"] = 'N/A' if not "links" in vers.keys(): vers["links"] = 'N/A' win1.addstr(2 , 1 , " Firmware version : " + vers[ 'design_version' ] , CYAN | curses.A_BOLD ) win1.addstr( ", for server : " + vers[ 'server' ] , CYAN | curses.A_BOLD ) win1.addstr( ", and number of links : " + vers[ 'links' ] , CYAN | curses.A_BOLD ) win1.refresh() win2 = stdscr.subwin(y_max/6, x_max - 2, y_max/6, 0) win2.box() win2.addstr(1, 1, "PLL SI54345_1", CYAN | curses.A_BOLD) win2.refresh() win3 = stdscr.subwin(y_max/6, x_max - 2, 2*y_max/6, 0) win3.box() win3.addstr(1, 1, "PLL SI54345_2", CYAN | curses.A_BOLD) win3.refresh() win4 = stdscr.subwin( y_max/6 , x_max-2 , 3*y_max/6, 0 ) win4.box() win4.addstr(1, 1, "PLL SI54344", CYAN | curses.A_BOLD) win4.refresh() win5 = stdscr.subwin(y_max/6, x_max -2, 4*y_max/6, 0) win5.box() win5.addstr(1, 1, "Clock FTSW", CYAN | curses.A_BOLD) win5.refresh() win6 = stdscr.subwin(y_max/6, x_max -2, 5*y_max/6, 0) win6.box() win6.addstr(1, 1, "F2: Program PLLs (source = FTSW), F3: Program PLLs (source = Osci.)", CYAN | curses.A_BOLD) win6.addstr(2, 1, "F4: Clear LOS/OOF/LOL Flag, F5 : Hard reset, F6: Soft reset", CYAN | curses.A_BOLD) win6.addstr(3, 1, "F7: Reset trigger counter, 0/1/2/3/4/5/6: Resynchronize b2link 0/1/2/3/4/5/6", CYAN | curses.A_BOLD) win6.addstr(4, 1, "a: Activate all channels, d: Deactivate all channels", CYAN | curses.A_BOLD) win6.refresh() # Loop where k is the last character pressed while (k != ord ('q')): # Initialization # height, width = stdscr.getmaxyx () if k == curses.KEY_DOWN: cursor_y = cursor_y + 1 elif k == curses.KEY_UP: cursor_y = cursor_y - 1 elif k == curses.KEY_RIGHT: cursor_x = cursor_x + 1 elif k == curses.KEY_LEFT: cursor_x = cursor_x - 1 elif k == curses.KEY_F2: win1.move(3, 1) win1.clrtobot() win1.box() win1.addstr(3, 1, "Programming PLLs (source = FTSW)" , curses.A_BOLD) files = files1b conf = conf1 program_plls(plls, devices, files, win1) win2.move(2, 1) win2.clrtobot() win2.box() win3.move(2, 1) win3.clrtobot() win3.box() win4.move(2, 1) win4.clrtobot() win4.box() elif k == curses.KEY_F3: win1.move(2, 1) win1.clrtobot() win1.box() win1.addstr(2, 1, "Programming PLLs (source = Oscillator) " , curses.A_BOLD) files = files2b conf = conf2 program_plls(plls, devices, files, win1) win2.move(2, 1) win2.clrtobot() win2.box() win3.move(2, 1) win3.clrtobot() win3.box() win4.move(2, 1) win4.clrtobot() win4.box() elif k == curses.KEY_F4: win1.move(2, 1) win1.clrtobot() win1.box() start_time = time.time() win1.addstr(3, 1, " Clearing input LOS and output LOL sticky bit ", WHITE) for i in plls.keys(): plls[i].clear_lol_flg_bit() plls[i].clear_los_oof_flg_reg() win1.refresh() elif k== curses.KEY_F5: line = 3 win1.move(2, 1) win1.clrtobot() win1.box() for i in plls.keys(): win1.addstr(line, 1, "Sending Hard reset to device "+devices[i]) plls[i].hard_reset() line = line + 1 win1.addstr(line, 1, "..... Done") line = line + 1 win1.refresh() elif k== curses.KEY_F6: line = 3 win1.move(2, 1) win1.clrtobot() win1.box() for i in plls.keys(): win1.addstr(line, 1, "Sending Soft reset to device "+devices[i]) plls[i].soft_reset() line = line + 1 win1.addstr(line, 1, "..... Done") line = line + 1 win1.refresh() elif k== ord('0'): fpga.resynchronizeLink(0) elif k== ord('1'): fpga.resynchronizeLink(1) elif k== ord('2'): fpga.resynchronizeLink(2) elif k== ord('3'): fpga.resynchronizeLink(3) elif k== ord('4'): fpga.resynchronizeLink(4) elif k== ord('5'): fpga.resynchronizeLink(5) elif k== curses.KEY_F7: fpga.resetTriggerCounter() elif k==ord('a'): fpga.activateAllChannels() elif k==ord('d'): fpga.deactivateAllChannels() # cursor_x = max (0, cursor_x) # cursor_x = min (width - 1, cursor_x) # # cursor_y = max (0, cursor_y) # cursor_y = min (height - 1, cursor_y) # Refresh windows with pll information pll_window(pll_si5345_1, devices[1], fpga, freq[1], conf[1], win2) pll_window(pll_si5345_2, devices[2], fpga, freq[2], conf[2], win3) pll_window(pll_si5344 , devices[3], fpga, freq[3], conf[3], win4) fanout_window(fpga, win5) # Refresh the screen #stdscr.refresh () # Wait for next input stdscr.nodelay (True) k = stdscr.getch () def main(): if (len(sys.argv) != 2): print "Missing argument" print "Syntax : config_PLLs <Nb_of_card> where Nb_of_pcie_slot = 0 or 2" exit() elif (sys.argv[1] == "0"): print print "===== Target board = 0" dev = 0 elif (sys.argv[1] == "2"): print print "===== Target board = 2" dev = 2 else: print "Wrong argument" print "Syntax : config_PLLs <Nb_of_card> where Nb_of_pcie_slot = 0 or 2" exit() curses.wrapper (draw_menu, dev) if __name__ == "__main__": size = subprocess.Popen("stty size", shell=True, stdout=subprocess.PIPE).stdout result = size.read() result = result.replace("\n","") y = int(result.split(" ")[0]) x = int(result.split(" ")[1]) print "Your window's x =" , x print "Your window's y =" , y if x < 79 or y < 34: print "Your terminal window is too small (should be at least x=80, y=35)" quit() main ()