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

import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc
from   pylab import *

if __name__ == '__main__':

    """
    Checks that the number of pre and post trigger samples are written to RAM.
    Sets firmware to the a test mode which writes the value of the addr to that addr location
    Reads the data back from the pre trig position and checks that the numbers are consecutive 
    right through to the end of post trig data.
    
    After every acquisiton in the mode mentioned previously, it switches back to the normal mode, 
    and allows a longer time before the acq so that the list of consecutive addresses are overwritten 
    in ram
    """



    GN4124_CSR = 0x0 
    ddr3_calib_done = 0x3 <<2

    # Commands and variables
    acq_start = 0x01
    acq_stop = 0x02
    decim_val = 1
    trig_delay_val = 0
    sw_trig = 0x00000001
    adc_cont_start = 1
    attempt_trig_read = 1
    software_trigger = 0
    integer_plot = 1
    thresh_trig = 0
    
    #Threshold Conditions
    trigger_threshold=0x0001
    slope=0
    channel_for_thresh_trig=0x6
    sw_trig_en=1
    hw_trig_en=0
    
    # acquires settings from user
    shots_num = int(raw_input("input shots number : "))
    pre_trig_val = int(raw_input(" input pre trig number : "))
    post_trig_val =int(raw_input(" input post trig number : "))
    num_it = int(raw_input("set number of test loop iterations : "))
    
    test_data =0  
    error_position =[]
    
    #trigger_register=((trigger_threshold<<16)+(0x0<<8)+(slope<<7)+(channel_for_thresh_trig<<2)+(sw_trig_en<<1) +hw_trig_en)

    # Objects declaration
    spec = rr.Gennum() # bind to the SPEC board
    gn4124 = gn4124.CGN4124(spec, GN4124_CSR)
    fmc = fmc_adc.CFmcAdc100ks(spec)


    # Why am i not using the test suite version and does it matter?
    
    # Set up memory pages
    pages = gn4124.get_physical_addr()
   
    # CSR CONFIGURATION
    fmc.set_shots(shots_num)
    time.sleep(.1)
    fmc.set_pre_trig_samples(pre_trig_val)
    time.sleep(.1)
    fmc.set_post_trig_samples(post_trig_val)
    time.sleep(.1)
    fmc.set_decimation(decim_val)
    time.sleep(.1)
    fmc.set_trig_config(hw_trig_en, sw_trig_en, channel_for_thresh_trig, trigger_threshold, slope,trig_delay_val,thresh_trig)   
    time.sleep(.1)
    fmc.set_decimation(1)
    time.sleep(.1)
    
    
    for iteration in range(num_it):

    	    # Toggle between test data and normal mode
    	    test_data=~test_data & 0x1
    	    if test_data==1:
    		fmc.test_data_en()
    		time.sleep(.1)
    	    else:
    		fmc.test_data_dis()
    		time.sleep(.1)
    	    
    	    print "Test data %d"%test_data
    	   	    
	    # Stop Acq
	    fmc.stop_acq()
	    fmc.get_status()
	    while fmc.get_status()!=0x1:
	    	time.sleep(.1)
	    
	    # Start Acq
	    fmc.start_acq()
	    fmc.start_adc_cont()
	    time.sleep(.1)
	    
	    # If a software trigger test
	    if sw_trig_en==1:
	    	    # Wait for State machine to reach correct state
	    	    while fmc.get_status() !=3: #"WAIT_TRIG"	
			time.sleep(.1)
			
	    if test_data == 1:
	    	time.sleep(1)
	    	print "Sleep for 0.5 second"
	    else:
	    	time.sleep(3)
		print "Sleep for 3 seconds - allows test results to be erased"

	    if sw_trig_en==1:
	    	if shots_num>1:
			for i in range(shots_num-1):    	
				fmc.sw_trig()
				smething=raw_input("Press Enter once you have changed signal type")
				while fmc.get_status()!=0x3:
					time.sleep(.2)
			fmc.sw_trig()
		else:	
			fmc.sw_trig()
			print "Single Shot Trigger Applied"
			fmc.get_shots()
	    else:
		while fmc.get_status()!=0x1:
			time.sleep(1)
	
	    time.sleep(.1)

	    # CHECK IF DDR3 SYNCED PROPERLY:
	    while fmc.check_ddr3_calib()!=0x1:
	    	time.sleep(.5)
	    	print "DDR not calibrated..."


	    # Find trigger position - bottom 16 bits of register
	    trigger_position=fmc.get_trig_pos() & 0xFFFFFFFF
	    
	    # Define Where the acquisition starts
	    dma_start = trigger_position  - (pre_trig_val*8)
	    dma_end   = trigger_position + 7 +(post_trig_val*8)

	    page1_data_before = gn4124.get_memory_page(1)
	    dma_length = 0x1000 # DMA length in bytes  
	    
	    # READ FROM DDR TO MEMORY PAGES
	    #if (dma_end-dma_start)<=dma_length:
	    print "DMA LENGTH: ", dma_length
	    print "DMA START :", dma_start
	    print "DMA START (hex): ", hex(dma_start)
	    print "DMA END: ", dma_end
	    print "DMA END (hex): ", hex(dma_end)
	    print "trigger_position: ", trigger_position
	    print "trigger position (hex): ", hex(trigger_position)
	    print "DMA ACCESS LENGTH REQUIRED = ", dma_end-dma_start +1


	    # Retrieve 3 Pages of Data
	    if shots_num>1:
	    	print "DMA from Start of RAM"
		gn4124.add_dma_item(0*dma_length,pages[1], dma_length, 0,1)
	    	gn4124.add_dma_item(1*dma_length,pages[2], dma_length, 0,1)
	    	gn4124.add_dma_item(1*dma_length,pages[3], dma_length, 0,0)

	    else:
		gn4124.add_dma_item((dma_start<<2)+(0*dma_length),pages[1], dma_length, 0,1)
	    	gn4124.add_dma_item((dma_start<<2)+(1*dma_length),pages[2], dma_length, 0,1)
	    	gn4124.add_dma_item((dma_start<<2)+(2*dma_length),pages[3], dma_length, 0,0)
	    		
	    # DMA
	    page0_data = gn4124.get_memory_page(0)
	    print("DMA controller status : %s") % gn4124.get_dma_status()
	    print '\n Start DMA transfer'
	    gn4124.start_dma()
	    while('Done' != gn4124.get_dma_status()):
		print("DMA controller status : %s") % gn4124.get_dma_status()
		time.sleep(.5)
	    print '\nWaiting for interrupt'
	    gn4124.wait_irq()               
	    print '\nInterrupt received'
	    print("DMA controller status : %s") % gn4124.get_dma_status()
	    	    
	    page1_data = gn4124.get_memory_page(1)
	    page2_data = gn4124.get_memory_page(2)
	    page3_data = gn4124.get_memory_page(3)
	
	    channels 	  = []
	    channels_test = []
	    
	    for i in range(2**10):
	    	channels_test.append(page1_data[i]&0xFFFFFFFF)
	    for i in range(2**10):
	    	channels_test.append(page2_data[i]&0xFFFFFFFF)
	    
	    if test_data == 1:
	    	print "\n\nExpected start position",hex(dma_start)	
	    	print "Start address read", hex(channels_test[0])
	    	if hex(dma_start) !=hex(channels_test[0] ):
	    		print "Error : Data received from address does not equal address value"
	    		raw_input("Examine data : Press Enter to continue  ")
	
	    for i in range(2**10):
	    	channels.append(page1_data[i] >>16 )
		channels.append(page1_data[i] & 0xFFFF)

	    for i in range(2**10):
	    	channels.append(page2_data[i]>>16) 
		channels.append(page2_data[i] & 0xFFFF)

	    #CONVERT FROM 2s COMPLIMENT
	    if integer_plot==1:
		    for i in range(len(channels)):
			if(channels[i] & 0x8000):
				channels[i] = -0x10000 + channels[i]
	    
	    # SORT INTO CHANNELS
	    time_base = arange(0,(len(channels)/16),1)
	    channel1 = channels[0::16]
	    channel2 = channels[1::16]
	    channel3 = channels[2::16]
	    channel4 = channels[3::16]
	    channel5 = channels[4::16]
	    channel6 = channels[5::16]
	    channel7 = channels[6::16]
	    channel8 = channels[7::16]
	    channel9 = channels[8::16]
	    channel10 = channels[9::16]
	    channel11 = channels[10::16]
	    channel12 = channels[11::16]
	    channel13 = channels[12::16]
	    channel14 = channels[13::16]
	    channel15 = channels[14::16]
	    channel16 = channels[15::16]
	   
	    # WRITE TO FILE
	    file = open("adc_100k_acq.txt", 'w')
	    for i in range(len(channel1)):
		if integer_plot==1:        
			file.write("%5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d, %5d\n" % (time_base[i], channel1[i], channel2[i], channel3[i], channel4[i], channel5[i], channel6[i], channel7[i], channel8[i], channel9[i], channel10[i], channel11[i], channel12[i], channel13[i], channel14[i], channel15[i], channel16[i]))
		else:
			file.write("%5d, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X, %5X\n" % (time_base[i], channel1[i], channel2[i], channel3[i], channel4[i], channel5[i], channel6[i], channel7[i], channel8[i], channel9[i], channel10[i], channel11[i], channel12[i], channel13[i], channel14[i], channel15[i], channel16[i]))
	   
	   
	    # Length of acq in terms of 32 bit words	   
	    length_of_acq = (pre_trig_val*8)+8+(post_trig_val*8)
	    print "length of acquisition in 32bit words: ", length_of_acq
	    print "num of acqs = ",(length_of_acq/8) 
	    pos_of_break = []
	   
	    # Loop just passed the acq lenghts  
	    if test_data==1:
	    	for j in range(length_of_acq+10):
	    		# Look for break in consecutive numbers
	    		if channels_test[j]!=channels_test[j+1]-1 :
	    			# Note the position of the break
	    			pos_of_break.append(j)
	    			
	    	print pos_of_break
	    	if (pos_of_break[0]+1)==length_of_acq:
	    		print "No problems"
	    	else:
	    		error_position.append(pos_of_break[0])
	   		raw_input("Press Enter Once the data has been examined")
    	    print "Number of errors = ",len(error_position)	
    	    print "Iteration number ",iteration	
    				
    print "Number of errors", len(error_position)
    print "Position of Errors", error_position
    print "Predicted positon of change : ",length_of_acq

    
    
    print '\nBye bye ...'
    sys.exit()
