#!/usr/bin/python
#===============================================================================
# CERN (BE-CO-HT)
# Retrieve gateware version from CONV-TTL-BLO board
#===============================================================================
# author: Theodor Stana (t.stana@cern.ch)
#         Maciej Suminski (maciej.suminski@cern.ch)
#
# date of creation:
#
# version: 1.1
#
# description:
#   This script retrieves the value of the CONV-TTL-BLO status register and
#   retrieves the GWVERS field of the register.
#
#===============================================================================
# GNU LESSER GENERAL PUBLIC LICENSE
#===============================================================================
# This source file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation; either version 2.1 of the License, or (at your
# option) any later version. This source is distributed in the hope that it
# will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details. You should have
# received a copy of the GNU Lesser General Public License along with this
# source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
#===============================================================================
# last changes:
#    2014-05-02    Theodor Stana        Changed to print the bits of the SR
#                                       in turn.
#    2017-02-02    M. Suminski          Updated mem map to match v4 gateware
#===============================================================================
#  TODO: -
#===============================================================================
import sys
sys.path.append("../ei2c")
from ei2c import *
import ei2cdefine
sys.path.append("..")
import convttl_regs as regs

if __name__ == "__main__":

    # Get the IP, user and password for the ELMA crate from either user input,
    # or ei2cdefine.py
    if (ei2cdefine.ENABLED):
        ip   = ei2cdefine.HNAME
        user = ei2cdefine.USER
        pwd  = ei2cdefine.PWD
    else:
        ip   = raw_input("ELMA crate IP or hostname : ")
        user = raw_input("ELMA crate user name      : ")
        pwd  = raw_input("ELMA crate password       : ")
    testelma = EI2C(ip, user, pwd)
    testelma.open()

    # Ask for slot number
    while 1:
        try:
            slot = raw_input("Slot no.: ")
            slot = int(slot)
            break
        except TypeError as e:
            print("Please input a decimal slot number.")
        except SlotError as e:
            print(e.strerror)
        except KeyboardInterrupt:
            sys.exit();
        except:
            print("Unexpected error: ", sys.exc_info()[0])

    # Print which board is detected in the selected slot
    bid = testelma.get_bid(slot)

    # Get status register value and print
    v = testelma.read(slot, regs.SR)
    print("Status register    : 0x%08x" % v)
    print("===============================")

    # Strip GWVERS and print
    maj = (v & 0xf0) >> 4
    min = v & 0x0f
    print("Gateware version   : v%d.%d (0x%02x)" % (maj, min, v & 0xff))

    if maj < 4:
        print("This tool works with gateware v4. Please upgrade your gateware.")
        sys.exit()

    # Strip SWITCHES and print
    switches = (v & 0xff00) >> 8
    print("Switches           : 0x%02x" % switches)

    # Negate in case g/w version is less than 3.0, or golden less than 0.2.
    # Gateware versions below these two had the switches active-low.
    # This negation is done to allow correct printing of ON or OFF states.
    if ((bid == "TBLO") and
            (((maj == 0) and (min < 2)) or ((maj != 0) and (maj < 3)))):
        switches ^= 0xff
    if (switches & 0x80):
        print("  TTL mode         : TTL")
    else:
        print("  TTL mode         : TTL-BAR")
    if (switches & 0x02):
        print("  Pulse length     : short (250 ns)")
    else:
        print("  Pulse length     : long (1.25 us)")
    if (switches & 0x01):
        print("  Glitch filter    : on")
    else:
        print("  Glitch filter    : off")

    # Strip RTM and print
    rtm  = (v & 0x3f0000) >> 16
    rtmm = rtm & 0x7
    rtmp = (rtm & 0x3f) >> 3
    if ((bid == "TBLO") and
            (((maj == 0) and (min < 2)) or ((maj != 0) and (maj < 3)))):
        print("-------------------------------")
        print("Note: negated w.r.t. latest user guide version")
    print("RTM detection      : 0x%02x" % rtm)
    print("  RTMM[2:0]        : %s" % ("{0:#05b}".format(rtmm)[2:]))
    print("  RTMP[2:0]        : %s" % ("{0:#05b}".format(rtmp)[2:]))
    if ((maj == 0) and (min < 2)) or (maj < 3):
        print("-------------------------------")

    # Hardware version
    hwver = (v & 0x03c00000) >> 22
    print("Hardware version   : %s"
            % (str(hwver) if hwver >= 4 else "3 or below" ))

    # White Rabbit present
    wrpres = (v & 0x04000000) >> 8
    print("White Rabbit       : %s" % ("present" if wrpres else "absent"))


    # Get error register value and print
    v = testelma.read(slot, regs.ERR)
    print("Error register     : 0x%08x" % v)
    print("===============================")

    print("I2C timeout error  : %s" % ("{0:#01b}".format(int(bool(v & (1 << 0))))[2]))
    print("I2C address error  : %s" % ("{0:#01b}".format(int(bool(v & (1 << 1))))[2]))
    print("Pulse frequency limit error : 0x%02x" % ((v & 0x000000fc) >> 2))
    print("  CH1              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 2))))[2]))
    print("  CH2              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 3))))[2]))
    print("  CH3              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 4))))[2]))
    print("  CH4              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 5))))[2]))
    print("  CH5              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 6))))[2]))
    print("  CH6              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 7))))[2]))
    print("Pulse watchdog error : 0x%02x" % ((v & 0x00003f00) >> 8))
    print("  CH1              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 8))))[2]))
    print("  CH2              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 9))))[2]))
    print("  CH3              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 10))))[2]))
    print("  CH4              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 11))))[2]))
    print("  CH5              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 12))))[2]))
    print("  CH6              : %s" % ("{0:#01b}".format(int(bool(v & (1 << 13))))[2]))

    testelma.close()
