#!/usr/bin/python
#===============================================================================
# CERN (BE-CO-HT)
# Long-term register update test
#===============================================================================
# author: Theodor Stana (t.stana@cern.ch)
#
# date of creation: 2014-08-25
#
# version: 1.0
#
# description:
#
# dependencies:
#
# references:
#===============================================================================
# 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-08-25    Theodor Stana     File created
#===============================================================================
#  TODO: -
#===============================================================================

import sys
sys.path.append("../ei2c");
from ei2c import *
import ei2cdefine
import time

if __name__ == "__main__":

    # Get the IP, user and password for the ELMA crate from ei2cdefine.py
    ip   = ei2cdefine.HNAME
    user = ei2cdefine.USER
    pwd  = ei2cdefine.PWD
    elma = EI2C(ip, user, pwd)
    elma.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])

    # Ask how long to run the test
    print("")
    print("How long would you like to run the test?")
    while 1:
        try:
            hrs = raw_input("  hrs: ")
            hrs = int(hrs)
            if (hrs < 0):
                raise Exception
            break
        except KeyboardInterrupt:
            sys.exit()
        except:
            print("    Hours must be a decimal number >= 0!")

    while 1:
        try:
            mins = raw_input("  mins: ")
            mins = int(mins)
            if (mins < 0):
                raise Exception
            break
        except KeyboardInterrupt:
            sys.exit()
        except:
            print("    Minutes must be a decimal number >= 0!")

    while 1:
        try:
            secs = raw_input("  secs: ")
            secs = int(secs)
            if (secs < 0):
                raise Exception
            break
        except KeyboardInterrupt:
            sys.exit()
        except:
            print("    Seconds must be a decimal number >= 0!")

    # Fill up current and previous register init values with current reg values
    chpcr = []
    chltscyr = []
    chltstlr = []
    chltsthr = []
    for i in range(4):
        chpcr.append([])
        chltscyr.append([])
        chltstlr.append([])
        chltsthr.append([])
    chpcr_p = []
    chltscyr_p = []
    chltstlr_p = []
    chltsthr_p = []
    for i in range(4):
        chpcr_p.append([])
        chltscyr_p.append([])
        chltstlr_p.append([])
        chltsthr_p.append([])
    chpcr[1]      = []
    chltscyr[1]   = []
    chltstlr[1]   = []
    chltsthr[1]   = []
    chpcr_p[1]    = []
    chltscyr_p[1] = []
    chltstlr_p[1] = []
    chltsthr_p[1] = []
    chpcr[3]      = []
    chltscyr[3]   = []
    chltstlr[3]   = []
    chltsthr[3]   = []
    chpcr_p[3]    = []
    chltscyr_p[3] = []
    chltstlr_p[3] = []
    chltsthr_p[3] = []
    for i in range(0, 6):
        chpcr[1].append(elma.read(slot, 0x0c + 4*i))
        chltscyr[1].append(elma.read(slot, 0x40 + 0xc*i))
        chltstlr[1].append(elma.read(slot, 0x44 + 0xc*i))
        chltsthr[1].append(elma.read(slot, 0x48 + 0xc*i) & 0xff)
        chpcr_p[1].append(chpcr[1][i])
        chltscyr_p[1].append(chltscyr[1][i])
        chltstlr_p[1].append(chltstlr[1][i])
        chltsthr_p[1].append(chltsthr[1][i])
        chpcr[3].append(elma.read(slot+2, 0x0c + 4*i))
        chltscyr[3].append(elma.read(slot+2, 0x40 + 0xc*i))
        chltstlr[3].append(elma.read(slot+2, 0x44 + 0xc*i))
        chltsthr[3].append(elma.read(slot+2, 0x48 + 0xc*i) & 0xff)
        chpcr_p[3].append(chpcr[1][i])
        chltscyr_p[3].append(chltscyr[3][i])
        chltstlr_p[3].append(chltstlr[3][i])
        chltsthr_p[3].append(chltsthr[3][i])

    # Compute test end time according to current time
    #
    # time.time() returns time since start of epoch
    # in seconds, so add secs, mins and hrs to that
    start_time = time.time()
    end_time = start_time + secs + 60*mins + 3600*hrs

    # Generate output file named according to current time
    # Write current time and start of test to output file
    print("%s: starting test" % time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()))

    # Run test loop for the specified time
    while time.time() < end_time:

        for i in range(0, 6):

            # Read values
            chpcr[slot][i]    = elma.read(slot, 0x0c + 4*i)
            chltscyr[slot][i] = elma.read(slot, 0x40 + 0xc*i)
            chltstlr[slot][i] = elma.read(slot, 0x44 + 0xc*i)
            chltsthr[slot][i] = elma.read(slot, 0x48 + 0xc*i) & 0xff

            # check CHxPCR not lower and within a tolerance limit of value before
            if (chpcr[slot][i] < chpcr_p[slot][i]) or (chpcr[slot][i] > chpcr_p[slot][i] + 14000):
                print("ERROR (%d / %s): CH%dPCR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chpcr_p[slot][i], chpcr[slot][i]))
            elif (chpcr[slot][i] > chpcr_p[slot][i]+4200):
                print("WARNING (%d / %s): CH%dPCR value: (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chpcr_p[slot][i], chpcr[slot][i]))

            # If no a stable value is written to the reg, the previous TAILR
            # should not have decremented, and should not have increased by
            # more than 3 (not more than 3s between pulses)
            if (chltstlr[slot][i] < chltstlr_p[slot][i]) or (chltstlr[slot][i] > chltstlr_p[slot][i]+3):
                print("ERROR (%d / %s): CH%dTAILR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltstlr_p[slot][i], chltstlr[slot][i]))
            elif (chltstlr[slot][i] > chltstlr_p[slot][i]+2):
                print("WARNING (%d / %s): CH%dLTSTLR value: (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltstlr_p[slot][i], chltstlr[slot][i]))

            # Same goes for TAIHR, except here we allow for a +1 (TAILR overflow)
            if (chltsthr[slot][i] < chltsthr_p[slot][i]) or (chltsthr[slot][i] > chltsthr_p[slot][i]+1):
                print("ERROR (%d / %s): CH%dLTSTHR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltsthr_p[slot][i], chltsthr[slot][i]))

            # Store value to "previous" array
            chpcr_p[slot][i]    = chpcr[slot][i]
            chltscyr_p[slot][i] = chltscyr[slot][i]
            chltstlr_p[slot][i] = chltstlr[slot][i]
            chltsthr_p[slot][i] = chltsthr[slot][i]

#            print(slot)
#            print("CH%dPCR=%d" % (i+1, chpcr[slot][i]) )
#            print("CH%dPLTSCYR=%d" % (i+1, chltscyr[slot][i]) )
#            print("CH%dPLTSTLR=%d" % (i+1, chltstlr[slot][i]) )
#            print("CH%dPLTSTHR=%d" % (i+1, chltsthr[slot][i]) )

        slot += 2

        for i in range(0, 6):

            # Read values
            chpcr[slot][i]    = elma.read(slot, 0x0c + 4*i)
            chltscyr[slot][i] = elma.read(slot, 0x40 + 0xc*i)
            chltstlr[slot][i] = elma.read(slot, 0x44 + 0xc*i)
            chltsthr[slot][i] = elma.read(slot, 0x48 + 0xc*i) & 0xff

            # check CHxPCR not lower and within a tolerance limit of value before
            if (chpcr[slot][i] < chpcr_p[slot][i]) or (chpcr[slot][i] > chpcr_p[slot][i] + 14000):
                print("ERROR (%d / %s): CH%dPCR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chpcr_p[slot][i], chpcr[slot][i]))
            elif (chpcr[slot][i] > chpcr_p[slot][i]+4200):
                print("WARNING (%d / %s): CH%dPCR value: (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chpcr_p[slot][i], chpcr[slot][i]))

            # If no a stable value is written to the reg, the previous TAILR
            # should not have decremented, and should not have increased by
            # more than 3 (not more than 3s between pulses)
            if (chltstlr[slot][i] < chltstlr_p[slot][i]) or (chltstlr[slot][i] > chltstlr_p[slot][i]+3):
                print("ERROR (%d / %s): CH%dTAILR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltstlr_p[slot][i], chltstlr[slot][i]))
            elif (chltstlr[slot][i] > chltstlr_p[slot][i]+2):
                print("WARNING (%d / %s): CH%dLTSTLR value: (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltstlr_p[slot][i], chltstlr[slot][i]))

            # Same goes for TAIHR, except here we allow for a +1 (TAILR overflow)
            if (chltsthr[slot][i] < chltsthr_p[slot][i]) or (chltsthr[slot][i] > chltsthr_p[slot][i]+1):
                print("ERROR (%d / %s): CH%dLTSTHR unexpected value (%d / %d)" % (
                        slot, time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()),
                        i+1, chltsthr_p[slot][i], chltsthr[slot][i]))


            # Store value to "previous" array
            chpcr_p[slot][i]    = chpcr[slot][i]
            chltscyr_p[slot][i] = chltscyr[slot][i]
            chltstlr_p[slot][i] = chltstlr[slot][i]
            chltsthr_p[slot][i] = chltsthr[slot][i]

#            print(slot)
#            print("CH%dPCR=%d" % (i+1, chpcr[slot][i]) )
#            print("CH%dPLTSCYR=%d" % (i+1, chltscyr[slot][i]) )
#            print("CH%dPLTSTLR=%d" % (i+1, chltstlr[slot][i]) )
#            print("CH%dPLTSTHR=%d" % (i+1, chltsthr[slot][i]) )

        slot -= 2

    print("%s: ending test" % time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()))
