#!/usr/bin/python
#===============================================================================
# CERN (BE-CO-HT)
# Read the CONV-TTL-BLO timetag buffer
#===============================================================================
# author: Theodor Stana (t.stana@cern.ch)
#         Maciej Suminski (maciej.suminski@cern.ch)
#
# date of creation:
#
# version: 1.1
#
# description:
#   This script demonstrates reading the CONV-TTL-BLO timetag buffer down to the
#   last sample.
#
#===============================================================================
# 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:
#    2017-02-02    M. Suminski          Updated mem map to match v4 gateware
#===============================================================================
#  TODO: -
#===============================================================================
import sys
sys.path.append("../../ei2c")
from ei2c import *
import ei2cdefine
import math
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)

    # Output to file?
    while 1:
        try:
            inp = raw_input("Output samples to file? (y/n) ").lower()
            if (inp  == 'y'):
                fname = raw_input("File name (with extension): ");
                f = open(fname, 'w')
                break
            elif (inp == 'n'):
                break
        except KeyboardInterrupt:
            print("Exiting on user request")
            sys.exit();
        except:
            print("Error: " + sys.exc_info()[0]);

    # Read while FIFO is not empty
    csr   = testelma.read(slot, regs.TBCSR)
    empty = csr & (1 << 17)
    used  = csr & 0x7f

    chcnt = [0, 0, 0, 0, 0, 0]

    while not empty:
        # Read cycles and seconds counters
        cyc = testelma.read(slot, regs.TBCYR)
        sl  = testelma.read(slot, regs.TBTLR)
        sh  = testelma.read(slot, regs.TBTHR)

        # The seconds counter indicates actual seconds; the cycles counter
        # indicates 8-ns cycles, so convert to ns
        s   = (sh << 32) | sl
        ns  = cyc*8

        # Get contents of TBCSR
        csr   = testelma.read(slot, regs.TBCSR)
        empty = csr & (1 << 17)
        if (empty):
            break
        used  = csr & 0x7f

        # Get channel mask from meta register
        ch = testelma.read(slot, regs.TBMR) & 0x3f

        # Increment channel counters if channel bit is set in FIFO
        i = 0
        if (ch & (1 << i)):
            chcnt[i] += 1
        i += 1
        if (ch & (1 << i)):
            chcnt[i] += 1
        i += 1
        if (ch & (1 << i)):
            chcnt[i] += 1
        i += 1
        if (ch & (1 << i)):
            chcnt[i] += 1
        i += 1
        if (ch & (1 << i)):
            chcnt[i] += 1
        i += 1
        if (ch & (1 << i)):
            chcnt[i] += 1

        #ch = 1 + int(math.log(ch)/math.log(2))

        # And print
        sample = "(%3d) %s : %d.%09d sec" % (used, "{0:#08b}".format(ch)[2:], s, ns)
        if 'f' in locals():
            f.write(sample + '\n');
        else:
            print(sample)

    # Number of pulses are always printed to console
    print("Number of pulses:")
    i = 0
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1
    print("CH%d: %d" % (i+1, chcnt[i]))
    i += 1

    if 'f' in locals():
        f.close()
