#!   /usr/bin/env   python
#    coding: utf8

# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org


####### n=0; while [[ $n -lt 10 ]]; do echo Iteration $n; sudo ./test05_v2.py; n=$((n+1)); done | tee -a tmp.txt  #######

# Import system modules
import sys
import time
import os
import math
import pylab
from pylab import *


# Add common modules location tp path
sys.path.append('../../../')
sys.path.append('../../../gnurabbit/python/')
sys.path.append('../../../common/')

# Import common modules
from ptsexcept import *
import rr

# Import specific modules
import fmc_tdc
sys.path.append('../../../../fmc_delay/software/python/')
import fdelay_lib


"""
test07: Tests the accuracy of the Fine Delay delta
"""

def main (default_directory='.'):

    # Constants declaration
    FMC_TDC_ADDR = '1a39:0004/1a39:0004@000B:0000'
    FMC_TDC_BITSTREAM = '../firmwares/evas_tdc_irq8.bit'
    FMC_TDC_CHANNEL_NB = 5
    
    FMC_DELAY_ADDR = '1a39:0004/1a39:0004@0005:0000'
    FMC_DELAY_BITSTREAM = '../firmwares/fmc_delay_spec.bin'

    # SPEC object declaration
    spec = rr.Gennum()


    ###########################################################################
    # TDC
    ###########################################################################

    # Bind SPEC object to FMC TDC card
    print "-----------------------------------------------------------------"
    print "---------------------------- FMC TDC ---------------------------- "
    print "\n_______________________________Info______________________________\n"
    print "FMC TDC address to parse: %s"%(FMC_TDC_ADDR)
    for name, value in spec.parse_addr(FMC_TDC_ADDR).iteritems():
        print "%s:0x%04X"%(name, value)
    spec.bind(FMC_TDC_ADDR)

    # Load FMC TDC firmware
    print "\n_________________________Initialisations_________________________\n"
    print "Loading FMC TDC firmware...",
    spec.load_firmware(FMC_TDC_BITSTREAM)
    time.sleep(2)
    print "Firmware loaded!"

    # TDC object declaration
    tdc = fmc_tdc.CFMCTDC(spec)

    # TDC configuration
    print "\n__________________________Configuration__________________________\n"
    tdc.config_acam()
    tdc.set_irq_tstamp_thresh(0x100) # set to 
    tdc.set_irq_time_thresh(0xFF)   #  secs
    time.sleep(1)

    tdc.enable_channels()
    for ch in range(1,FMC_TDC_CHANNEL_NB+1):
        tdc.channel_term(ch, 1)

    # Enable TDC core interrupts
    #print "\n____________________________IRQ mask_____________________________\n"
    #print('Set IRQ enable mask: %.4X')%tdc.set_irq_en_mask(0xC)


    # Check ACAM status
    print "\n___________________________ACAM reset____________________________\n"
    tdc.reset_acam()
    print "\n___________________________ACAM status___________________________\n"
    acam_status_test = tdc.read_acam_status()-0xC4000800
    if acam_status_test == 0:
        print "ACAM status OK!"
    else:
        print "/!\ACAM not OK../!\ "


    # Readback all ACAM configuration regs
    print "\n_________________Reading back ACAM configuration_________________\n"
    tdc.readback_acam_config()


    # Enable timestamps aquisition
    print "\n_______________________Starting aquisition_______________________\n"
    tdc.start_acq()


    all_periods_min = []
    all_periods_max = []


    # several iterations of sending pulses and retrieving timestamps 
    for m in range(1):

        print "\n________________________Accuracy testing_________________________\n"

        #tdc.check_irq()
        time.sleep(10)
        print "IRQ iteration: %d // Overflows: %d // IRQ source: %d // Write pointer: %d \r"%(m, tdc.get_overflow_counter(), tdc.get_irq_src(), tdc.get_pointer()),


        timestamps = tdc.get_timestamps(1)

        r_edge_timestamps = []
        period_list = []
    
        for i in range(len(timestamps)):
             if ((timestamps[i][2] == 1) and (timestamps[i][1] == 4)):
                 r_edge_timestamps.append(timestamps[i][0])

        r_edge_timestamps.sort()

        for i in range(0,len(r_edge_timestamps)-1):
            period = r_edge_timestamps[i+1] - r_edge_timestamps[i]
            period_list.append(period)


        current_max = max(period_list)
        current_min = min(period_list)
        span = current_max-current_min
        print "\n__________________Itteration %d Accuracy Results_________________\n"%m
        print "Number of timestamps            : %d"%(len(timestamps))
        print "Max  of this itteration         : %15.3f ps"%max(period_list)
        print "Min  of this itteration         : %15.3f ps"%min(period_list)
        print "Span of this itteration         : %15.3f ps"%span

        if span > 1600:
            print "Span messed up!"
            for i in range(len(timestamps)):
                print timestamps[i]


        all_periods_max.append(current_max)
        all_periods_min.append(current_min)

        """
        print "Max so far found at itteration %d: %15.3f ps"%(all_periods_max.index(max(all_periods_max)), max(all_periods_max))
        print "Min so far found at itteration %d: %15.3f ps"%(all_periods_min.index(min(all_periods_min)), min(all_periods_min))
        print "Span so far                     : %15.3f ps"%((max(all_periods_max))-(min(all_periods_min)))

        """
    # out of the for loop!
    print "\n___________________________ACAM status___________________________\n"
    acam_status_test = tdc.read_acam_status()-0xC4000800
    if acam_status_test == 0:
        print "ACAM status OK!"
    else:
        print "/!\ACAM not OK../!\ "

    print "\n_______________________Stopping aquisition_______________________\n"
    tdc.stop_acq()

    """
    print "\n_______________________! Final Results !_________________________\n"
    #print all_periods_min
    #print all_periods_max
    print "\n\nAnd the final span after %d pulses is    %7.3f ps!\n"%((256*m), (max(all_periods_max))-(min(all_periods_min)))
    """

    print "\n-----------------------------------------------------------------\n\n\n"


if __name__ == '__main__' :
    main()
