#!   ./python
#    coding: utf8

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

# Import system modules
import sys
import time
import os

# Import specific modules
from fmc_adc_svec import *
from fmc_adc import *

# Import common modules
from ptsexcept import *
from rr2vv import *


"""
test34: Test interrupts
        Requires the interrupt timeout to be extended to 5000ms using vmeiotest
        Requires a pps pulse on trigger inputs.
"""

def main (default_directory='.'):

    # Constants declaration
    LUN = 0
    TEST_NB = 34
    FMC_ADC_BITSTREAM = '../../gatewares/svec_fmcadc100m14b4cha.bin'
    FMC_ADC_BITSTREAM = os.path.join(default_directory, FMC_ADC_BITSTREAM)
    EXPECTED_BITSTREAM_TYPE = 0x0
    NB_CHANNELS = 4


    start_test_time = time.time()
    print "\n================================================================================"
    print "==> [SVEC] Test%02d start\n" % TEST_NB

    print("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
    print("WARNING: interrupt timeout must be extended to 5000ms using vmeiotest.")
    print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n")

    # SVEC object declaration
    print "Loading hardware access library and opening device.\n"
    bus = VME_rr_compatible(LUN)
    print "Initialising device.\n"

    # Load FMC ADC gateware
    ask = ''
    while ((ask != "Y") and (ask != "N")) :
        ask = raw_input("Do you want to load the gateware: %s? [y,n]"%(FMC_ADC_BITSTREAM))
        ask = ask.upper()
        print " "

    if (ask == "Y"):
        print "Loading FMC ADC gateware: %s\n" % FMC_ADC_BITSTREAM
        bus.vv_init()
        ret = bus.vv_load(FMC_ADC_BITSTREAM, 1)
        print('')
        time.sleep(2)
    else:
        bus.vv_open()

    # Carrier object declaration (SPEC board specific part)
    try:
        carrier = CFmcAdc100mSvec(bus, EXPECTED_BITSTREAM_TYPE)
    except FmcAdc100mSvecOperationError as e:
        raise PtsCritical("Carrier init failed, test stopped: %s" % e)

    # Test carrier periherals
    print('\n-------------------------------------------------------------')
    print('[Carrier]')

    # Reset mezzanines
    #carrier.sw_rst(0)
    #carrier.sw_rst(1)

    carrier.print_unique_id()
    carrier.print_temp()

    # Mezzanines object declaration (FmcAdc100m14b4cha board specific part)
    fmc = []
    for i in range(2):
        try:
            print('\n-------------------------------------------------------------')
            print('[FMC slot %d]'%(i+1))
            mezz_offset = 0x2000+i*0x4000
            print('Mezzanine offset: 0x%08X'%(mezz_offset))
            fmc.append(CFmcAdc100m(bus, mezz_offset))
        except FmcAdc100mOperationError as e:
            raise PtsCritical("Mezzanine %d init failed, test stopped: %s" % (i+1, e))

    carrier.vic.print_regs()

    # Test mezzanines peripherals
    error = ['','']
    for i in range(2):
        try:
            print('\n-------------------------------------------------------------')
            print('[FMC slot %d]'%(i+1))

            print('')
            for j in range(1):

                print('Enable trigger interrupt')
                fmc[i].enable_trig_irq()
                fmc[i].print_eic_regs()

                fmc[i].set_ext_trig(0)
                fmc[i].print_trig_config()
                fmc[i].set_pre_trig_samples(500)
                fmc[i].set_post_trig_samples(500)
                fmc[i].set_shots(1)
                fmc[i].stop_acq()
                if fmc[i].get_acq_config_ok():
                    print("Acquisition config OK.")
                else:
                    raise FmcAdc100mSvecOperationError("Acquisition config NOT OK.")

                #fmc[i].fmc_adc_csr.print_reg_map()

                print "%d: Acquisition FSM state : %s (should be IDLE)" % (j,fmc[i].get_acq_fsm_state())
                fmc[i].start_acq()
                time.sleep(0.001)
                print "%d: Acquisition FSM state : %s (should be WAIT_TRIG)"% (j,fmc[i].get_acq_fsm_state())

                print "Wait for trigger."

                # Wait for interrupt
                ret = bus.vv_irqwait()
                print('[irq wait] Vector Address Register (VAR) = 0x%.8X'%ret)

                print('Check if interrupt is TRIGGER')
                irq_src = fmc[i].get_eic_src()
                irq_vect = carrier.vic_get_current_vector_addr()
                print("FMC%d EIC irq source : %.8X"%(i,irq_src))
                print("VIC current vector : 0x%08X"%irq_vect)
                if(irq_vect == carrier.fmc_eic_addr[i]):
                    if(fmc[i].get_trig_status()):
                        fmc[i].clear_trig_irq()
                        carrier.vic_ack_current_vector()
                        print("FMC%d EIC irq source : %.8X"%(i, fmc[i].get_eic_src()))
                    else:
                        raise FmcAdc100mSvecOperationError("Bad IRQ source : 0x%08X"%irq_src)
                else:
                    raise FmcAdc100mSvecOperationError("Bad IRQ vector. expected:0x%08X got:0x%08X" %(carrier.fmc_eic_addr[i], irq_vect))

                print('Disable trigger interrupt')
                fmc[i].disable_trig_irq()
                fmc[i].print_eic_regs()

            carrier.vic.print_regs()


        except FmcAdc100mOperationError as e:
            raise PtsError("Mezzanine %d interrupts test failed: %s" % (i+1, e))

    print('')
    print "==> End of test%02d" % TEST_NB
    print "================================================================================"
    end_test_time = time.time()
    print "[SVEC] Test%02d elapsed time: %.2f seconds\n" % (TEST_NB, end_test_time-start_test_time)

    if(error[0] != ''):
        raise PtsError('[FMC slot 1]' + error[0])
    if(error[1] != ''):
        raise PtsError('[FMC slot 2]' + error[1])

    bus.vv_close()


if __name__ == '__main__' :
    main()
