Skip to content
Snippets Groups Projects
pll_status_small.py 16.4 KiB
Newer Older
#!/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)
Patrick Robbe's avatar
Patrick Robbe committed
    win.addstr(3,1,'Run number : ' , curses.A_BOLD)
    win.addstr(3,14,'{0:4d}'.format(fpga.runNumber()),GREEN)
    win.addstr(3,20,'Trigger tag : '  , curses.A_BOLD )
    win.addstr(3,34, '{0:5d}'.format(fpga.triggerTag()) , GREEN )
    win.addstr(3,40, 'Clock Up : ' , curses.A_BOLD ) 
    if fpga.clockUp() == 1:
        win.addstr(3,51, 'OK' , GREEN )
    else:
        win.addstr(3,51,'NO',RED)
    win.addstr(3,55, 'TTD Up : ' , curses.A_BOLD ) 
    if fpga.ttdUp() == 1:
        win.addstr(3,64, 'OK' , GREEN )
    else:
        win.addstr(3,64,'NO',RED)
 
    win.addstr(3,68,'Trigger type : ' , curses.A_BOLD)
    win.addstr(3,83,'{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)
Patrick Robbe's avatar
Patrick Robbe committed
    for link in range( 4 ):
        if fpga.rxReadyIndividual(link) == 1:
            win.addstr(5,12+3*link, 'OK' , GREEN )
        else:
            win.addstr(5,12+3*link,'NO',RED)
    win.addstr(5,25,'TX ready : ' , curses.A_BOLD)
    for link in range( 4 ):
        if fpga.txReadyIndividual(link) == 1:
            win.addstr(5,36+3*link, 'OK' , GREEN )
        else:
            win.addstr(5,36+3*link,'NO',RED)
    win.addstr(5,50,'b2link ready : ' , curses.A_BOLD)
    for link in range( 4 ):
        if fpga.b2linkReadyIndividual( link ) == 1:
            win.addstr(5,65+3*link, 'OK' , GREEN )
        else:
            win.addstr(5,65+3*link,'NO',RED)
    win.refresh()

def program_plls(plls, devices, files, win):

    #win.move(2,1)
    win.clrtobot()
    win.box()
    line = 3

    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)
    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, F8/F9/F10/F11: Resynchronize b2link 0/1/2/3", 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(2, 1)
            win1.clrtobot()
            win1.box()
            win1.addstr(2, 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()
Patrick Robbe's avatar
Patrick Robbe committed
        elif k== curses.KEY_F8:
            fpga.resynchronizeLink(0)
        elif k== curses.KEY_F9:
            fpga.resynchronizeLink(1)
        elif k== curses.KEY_F10:
            fpga.resynchronizeLink(2)
        elif k== curses.KEY_F11:
            fpga.resynchronizeLink(3)
        elif k==curses.KEY_F7:
Patrick Robbe's avatar
Patrick Robbe committed
            fpga.resetTriggerCounter()

        # 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 ()