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

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

# Import system modules
import sys
import time
import os

# Add common modules and libraries location to path
sys.path.append('../../../')
sys.path.append('../../../gnurabbit/python/')
sys.path.append('../../../common/')


# Import common modules
from ptsexcept import *
import rr

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


"""
test34: Test interrupts (EIC + VIC)

Note: Requires test00.py to run first to load the firmware!
"""

def main (default_directory = '.'):

    # Constants declaration
    TEST_NB = 34
    EXPECTED_BITSTREAM_TYPE = 0x1

    PRE_TRIG_SAMPLES = 2000
    POST_TRIG_SAMPLES = 50000
    NB_SHOTS = 1


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

    # SPEC object declaration
    print "Loading hardware access library and opening device.\n"
    spec = rr.Gennum()

    # Carrier object declaration (SPEC board specific part)
    # Used to check that the firmware is loaded.
    try:
        carrier = CFmcAdc100mSpec(spec, EXPECTED_BITSTREAM_TYPE)
    except FmcAdc100mSpecOperationError as e:
        raise PtsCritical("Carrier init failed, test stopped: %s" % e)

    # Mezzanine object declaration (FmcAdc100m14b4cha board specific part)
    try:
        fmc = CFmcAdc100m(spec)
    except FmcAdc100mOperationError as e:
        raise PtsCritical("Mezzanine init failed, test stopped: %s" % e)


    try:

        #======================================================================
        # Print EIC and VIC registers
        carrier.vic.print_regs()
        carrier.vic.print_ivt()
        carrier.print_dma_eic_regs()
        fmc.print_eic_regs()

        #======================================================================
        # Test VIC with software interrupts
        print("\n\n--------------------------------------------------")
        print("Test VIC with software interrupts.\n")
        print("Simulate fmc0 interrupt")
        carrier.vic.sw_int(0)

        print("Wait for interrupt")
        carrier.gnum.wait_irq()

        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))
        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        time.sleep(0.5)
        print("Simulate dma interrupt")
        carrier.vic.sw_int(1)

        print("Wait for interrupt")
        carrier.gnum.wait_irq()

        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))
        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        #======================================================================
        # Test FMC interrupts (trigger, end of acq)
        print("\n\n--------------------------------------------------")
        print("Test FMC EIC (trigger, end of acquisition).\n")

        print("Configure acquisition")
        fmc.dc_offset_reset()
        fmc.set_soft_trig()
        fmc.set_pre_trig_samples(PRE_TRIG_SAMPLES)
        fmc.set_post_trig_samples(POST_TRIG_SAMPLES)
        fmc.set_shots(NB_SHOTS)
        fmc.set_decimation(1)

        print("Enable FMC EIC interrupts")
        fmc.enable_trig_irq()
        fmc.enable_acq_end_irq()
        print("FMC EIC interrupt enable mask: 0x%08X"%(fmc.get_eic_en_mask()))

        print("Make acquisition")
        fmc.stop_acq()
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()
        fmc.start_acq()
        time.sleep(0.01)
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()
        fmc.sw_trig()
        time.sleep(0.1)
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()

        print("Wait for interrupt")
        carrier.gnum.wait_irq()

        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        print(" ==> FMC EIC interrupt src   : 0x%08X"%(fmc.get_eic_src()))
        print("Clear trigger interrupt")
        fmc.clear_trig_irq()
        print("Clear end of acq interrupt")
        fmc.clear_acq_end_irq()
        print(" ==> FMC EIC interrupt src   : 0x%08X"%(fmc.get_eic_src()))

        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        #======================================================================
        # Test DMA interrupts (done, error)
        print("\n\n--------------------------------------------------")
        print("Test DMA EIC (done, error).\n")

        print("Configure DMA")
        trig_pos = fmc.get_trig_pos()
        carrier.cfg_dma((trig_pos-(PRE_TRIG_SAMPLES*8)), (PRE_TRIG_SAMPLES+POST_TRIG_SAMPLES)*8)

        print("Enable DMA interrupts")
        carrier.enable_dma_done_irq()
        carrier.enable_dma_error_irq()
        print("DMA EIC interrupt enable mask: 0x%08X"%(carrier.get_dma_eic_en_mask()))

        print("Start DMA")
        carrier.gnum.start_dma()

        print("Wait for interrupt")
        carrier.gnum.wait_irq()

        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        print(" ==> DMA EIC interrupt src   : 0x%08X"%(carrier.get_dma_eic_src()))
        print("Clear DMA done interrupt")
        carrier.clear_dma_done_irq()
        print(" ==> DMA EIC interrupt src   : 0x%08X"%(carrier.get_dma_eic_src()))

        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        #======================================================================
        # Test FMC and DMA interrupts
        print("\n\n--------------------------------------------------")
        print("Test FMC + DMA EIC (without acknowledge after FMC interrupts).\n")

        print("Configure acquisition")
        fmc.dc_offset_reset()
        fmc.set_soft_trig()
        fmc.set_pre_trig_samples(PRE_TRIG_SAMPLES)
        fmc.set_post_trig_samples(POST_TRIG_SAMPLES)
        fmc.set_shots(NB_SHOTS)

        print("Enable FMC EIC interrupts")
        fmc.enable_trig_irq()
        fmc.enable_acq_end_irq()
        print("FMC EIC interrupt enable mask: 0x%08X"%(fmc.get_eic_en_mask()))

        print("Enable DMA interrupts")
        carrier.enable_dma_done_irq()
        carrier.enable_dma_error_irq()
        print("DMA EIC interrupt enable mask: 0x%08X"%(carrier.get_dma_eic_en_mask()))

        print("Make acquisition")
        fmc.stop_acq()
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()
        fmc.start_acq()
        time.sleep(0.01)
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()
        fmc.sw_trig()
        time.sleep(0.1)
        #print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()

        print("Configure DMA")
        trig_pos = fmc.get_trig_pos()
        carrier.cfg_dma((trig_pos-(PRE_TRIG_SAMPLES*8)), (PRE_TRIG_SAMPLES+POST_TRIG_SAMPLES)*8)

        print("Start DMA")
        carrier.gnum.start_dma()

        time.sleep(1)

        print("Wait for interrupt")
        carrier.gnum.wait_irq()

        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        print(" ==> FMC EIC interrupt src   : 0x%08X"%(fmc.get_eic_src()))
        print("Clear trigger interrupt")
        fmc.clear_trig_irq()
        print("Clear end of acq interrupt")
        fmc.clear_acq_end_irq()
        print(" ==> FMC EIC interrupt src   : 0x%08X"%(fmc.get_eic_src()))

        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))


        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))

        print(" ==> DMA EIC interrupt src   : 0x%08X"%(carrier.get_dma_eic_src()))
        print("Clear DMA done interrupt")
        carrier.clear_dma_done_irq()
        print(" ==> DMA EIC interrupt src   : 0x%08X"%(carrier.get_dma_eic_src()))

        carrier.vic_ack_current_vector()
        print("Interrupt acknowledged")
        int_vect = carrier.vic_get_current_vector_addr()
        print(" ==> Interrupt vector address: 0x%08X"%(int_vect))
        raw_int = carrier.vic_get_raw_status()
        print(" ==> Raw interrupt status    : 0x%08X"%(raw_int))



    except(FmcAdc100mOperationError) as e:
        raise PtsError("Test failed: %s" % e)


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


if __name__ == '__main__' :
    main()
