#!/usr/bin/python
#===============================================================================
# CERN (BE-CO-HT)
# Long-term "no pulses at startup" test script
#===============================================================================
# author: Theodor Stana (t.stana@cern.ch)
#
# date of creation: 2014-05-09
#
# version: 1.0
#
# description:
#
#   Runs the startup test, which uses two ELMA crates, one of which is
#   power-cycled and the other one used as a means to detect if a pulse
#   was generated during power-up or power-down. At the end of the test,
#   an output file is created, containing the readout of the pulse counters
#   on the checking crate.
#
#   See the testing webpage [1] for more details and a connection diagram
#   between the two crates.
#
# dependencies:
#   ../ei2c/ei2c.py
#
# references:
#
#   [1] CONV-TTL-BLO testing webpage -- http://cern.ch/go/7Pwz
#
#===============================================================================
# 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-09    Theodor Stana     File created
#===============================================================================
#  TODO: -
#===============================================================================

import time
import sys
sys.path.append("../ei2c")
from ei2c import *
import subprocess
import os

#===============================================================================
# Change IPs/hostnames and logon credentials as appropriate
#   - dutip -- IP of DUT ELMA crate (the one being power-cycled)
#   - chkip -- IP of checking ELMA crate (the one not power-cycled)
dutip = ""
chkip = ""

# Note: the ADMIN logon credentials are required, assumed the same for both
# DUT and checking crate
user = ""
pwd  = ""
#===============================================================================

fnull = open(os.devnull, 'w')


def dut_elma_off():
    subprocess.call("snmpset -v2c -c " + pwd + " " + dutip + " "
            "1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 1", shell=True, stdout=fnull,
            stderr=fnull)
    time.sleep(7)

def dut_elma_on():
    subprocess.call("snmpset -v2c -c " + pwd + " " + dutip + " "
            "1.3.6.1.4.1.37968.1.1.7.2.1.3.1 i 0", shell=True, stdout=fnull,
            stderr=fnull)
    time.sleep(10)


if __name__ == "__main__":

    if (not dutip) or (not chkip) or (not user) or (not pwd):
        print("ERROR: One or more of the ELMA crate connection parameters "
                + "have not been set")
        sys.exit(-1)

#    dut_elma_off()
#    dut_elma_on()

    dutelma = EI2C(dutip, user, pwd)
    dutelma.open()

    chkelma = EI2C(chkip, user, pwd)
    chkelma.open()

    # Ask how long to run the test
    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!"

    # 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
    fname = time.strftime("s-%Y-%m-%d-%Hh%M", time.localtime()) + ".txt"
    f     = open(fname, "w")

    switch = []

    for i in range(4):
        switch.append("OFF")

    f.write("TTL switch readout\n")
    if not (dutelma.read(1, 0x04) & (0x8000)):
       switch[0] = "ON"
    if not (dutelma.read(2, 0x04) & (0x8000)):
       switch[1] = "ON"
    if not (chkelma.read(1, 0x04) & (0x8000)):
       switch[2] = "ON"
    if not (chkelma.read(2, 0x04) & (0x8000)):
       switch[3] = "ON"

    f.write("  DUT1: TTL switch %s\n" % switch[0])
    f.write("  DUT2: TTL switch %s\n" % switch[1])
    f.write("  CHK1: TTL switch %s\n" % switch[2])
    f.write("  CHK2: TTL switch %s\n" % switch[3])

    f.write('\n')
    f.write("Reading from ELMA crate used for checking (the one not power-cycled)\n")
    f.write('\n')
    f.write("Format in outputs if error:\n")
    f.write("date and time / iteration number / slot number : " +
              "[CH1 counter, CH2 counter, CH3 counter, CH4 counter," +
              "CH5 counter, CH6 counter]\n")
    f.write('\n')

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

    chcnt1 = [0, 0, 0, 0, 0, 0]
    chcnt2 = [0, 0, 0, 0, 0, 0]
    cntcmp = [0, 0, 0, 0, 0, 0]

    i = 0
    errcnt1 = 0
    errcnt2 = 0

    # Run test loop for the specified time
    while time.time() < end_time:
        # Increment iteration number
        i += 1

        # Power-cycle ELMA
        dut_elma_off()
        dut_elma_on()

        # Read counters and print errors
        chcnt1[0] = chkelma.read(1, 0x0c)
        chcnt1[1] = chkelma.read(1, 0x10)
        chcnt1[2] = chkelma.read(1, 0x14)
        chcnt1[3] = chkelma.read(1, 0x18)
        chcnt1[4] = chkelma.read(1, 0x1c)
        chcnt1[5] = chkelma.read(1, 0x20)

        if not (chcnt1 == cntcmp):
            errcnt1 += 1
            errmsg = ("ERROR (%s / iter %d / slot 1) : [%d, %d, %d, %d, %d, %d]" %
                    (time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()), i,
                    chcnt1[0], chcnt1[1], chcnt1[2], chcnt1[3],
                    chcnt1[4], chcnt1[5]))
            f.write(errmsg + "\n")
            #print(errmsg)

        chcnt2[0] = chkelma.read(2, 0x0c)
        chcnt2[1] = chkelma.read(2, 0x10)
        chcnt2[2] = chkelma.read(2, 0x14)
        chcnt2[3] = chkelma.read(2, 0x18)
        chcnt2[4] = chkelma.read(2, 0x1c)
        chcnt2[5] = chkelma.read(2, 0x20)

        if not (chcnt2 == cntcmp):
            errcnt2 += 1
            errmsg = ("ERROR (%s / iter %d / slot 2) : [%d, %d, %d, %d, %d, %d]" %
                    (time.strftime("%Y-%m-%d-%Hh%Mm%Ss", time.localtime()), i,
                    chcnt2[0], chcnt2[1], chcnt2[2], chcnt2[3],
                    chcnt2[4], chcnt2[5]))
            f.write(errmsg + "\n")
            #print(errmsg)

        # Clear counters
        chkelma.write(1, 0x0c, 0)
        chkelma.write(1, 0x10, 0)
        chkelma.write(1, 0x14, 0)
        chkelma.write(1, 0x18, 0)
        chkelma.write(1, 0x1c, 0)
        chkelma.write(1, 0x20, 0)

        chkelma.write(2, 0x0c, 0)
        chkelma.write(2, 0x10, 0)
        chkelma.write(2, 0x14, 0)
        chkelma.write(2, 0x18, 0)
        chkelma.write(2, 0x1c, 0)
        chkelma.write(2, 0x20, 0)


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

    f.write("Number of iterations      : %d\n" % i)
    f.write("Number of errors (slot 1) : %d\n" % errcnt1)
    f.write("Number of errors (slot 2) : %d\n" % errcnt2)

    # Print output file name
    print("")
    print("Test results can be found in " + fname)

    # Close connections and exit
    dutelma.close()
    chkelma.close()

