/*****************************************************************************

Copyright (c) 2006 Analog Devices, Inc.	All	Rights Reserved. 

This software is proprietary and confidential to Analog	Devices, Inc. 
and	its	licensors.

*****************************************************************************

$RCSfile: VideoInEdgeDetection_System.c,v $
$Revision: 1.3 $
$Date: 2007/11/13 00:48:08 $

Project:	BlackfinSDK (Edge Detection on ITU656 Video In)
Title:		System service routines
Author(s):	bmk
Revised	by:	

Description:
			Configures system, start devices and manages PPI/Pushbutton callbacks
			for Edge Detection on ITU 656 Video Input. 

References:
			None

*****************************************************************************
Tab	Setting:			4

Target Processor:		ADSP-BF5xx
Target Tools Revision:	ADSP VisualDSP++ v4.5
******************************************************************************

Modification History:
====================
$Log: VideoInEdgeDetection_System.c,v $
Revision 1.3  2007/11/13 00:48:08  randreol
Changed Deferred callback

Revision 1.2  2007/06/21 06:01:11  randreol
Added ssl_init changes

Revision 1.1  2007/05/22 18:38:06  gstephan
Creating VDSP 5.00 release folder.  Created from the head copy of
VDSP 4.50 release folder.

Revision 1.3  2006/07/06 07:26:28  bmk
modified project to use video utility file macros

Revision 1.2  2006/07/04 05:33:19  bmk
added Slide-show mode for BF533

Revision 1.1  2006/06/30 01:33:55  bmk
Initial entry


******************************************************************************
Include files
*****************************************************************************/

#include <VideoInEdgeDetection_System.h>	// Video In Edge Detection system includes
#include <drivers\encoder\adi_adv717x.h>	// video encoder driver includes
#include <drivers\decoder\adi_adv7183.h>	// video decoder driver includes
#include <drivers\twi\adi_twi.h>			// TWI driver includes
#include <SDK-ezkitutilities.h>				// EZ-Kit utility definitions
#include <adi_ssl_init.h>           // initialization sizings

// Place all data in SDRAM
#pragma default_section (DATA,"sdram_bank1")

/*****************************************************************************
Macros
*****************************************************************************/
//local data and handles
// Deferred Callback Manager data (memory for 1 service plus 6 posted callbacks)
static u8 DCBMgrData[ADI_DCB_QUEUE_SIZE + (ADI_DCB_ENTRY_SIZE)*6];

/*********************************************************************
Local function prototypes
*********************************************************************/
// initialises Ez-Kit button
void		InitButton 			(ADI_FLAG_ID);

/*****************
Callback functions
******************/
// Exception handler
static		ADI_INT_HANDLER		(ExceptionHandler);
// Hardware error handler
static		ADI_INT_HANDLER		(HWErrorHandler);
// Video In callback function (for ADV7183)
static void VideoInCallback		(void *AppHandle, u32  Event, void *pArg);
// Video Out callback function (for ADV717x)
static void VideoOutCallback	(void *AppHandle, u32  Event, void *pArg);
// Ez-Kit Button press callback function
static void ButtonPressCallback	(void *AppHandle, u32  Event, void *pArg);

/*********************************************************************
Globals
**********************************************************************
Device Driver and System Services Handles
*****************************************/
ADI_DCB_HANDLE				DCBManagerHandle;		// handle to the callback service Manager
ADI_DEV_DEVICE_HANDLE 		ADV7183DeviceHandle;	// handle to the ADV7183 device driver
ADI_DEV_DEVICE_HANDLE 		ADV717xDeviceHandle;	// handle to the ADV717x device driver

EDGE_DETECTION_SYSTEM_FLAGS	SystemFlag;				// System Flags	

static int Result;
/*****************************************************************************
Device Configuration tables
*****************************************************************************/

#if defined(__ADSPBF533__)

	// BF533 Ports (PF0=SCL,PF1=SDA) & Timer(Timer 0) used for Pseudo TWI
	adi_twi_pseudo_port port={ADI_FLAG_PF0,ADI_FLAG_PF1,ADI_TMR_GP_TIMER_0,(ADI_INT_PERIPHERAL_ID)NULL};

#elif defined(__ADSPBF561__)	

	// BF561 Ports (PF0=SCL,PF1=SDA) & Timer(Timer 2) used for Pseudo TWI
	adi_twi_pseudo_port port={ADI_FLAG_PF0,ADI_FLAG_PF1,ADI_TMR_GP_TIMER_2,(ADI_INT_PERIPHERAL_ID)NULL};

#endif

#if defined(__ADSPBF533__) || defined (__ADSPBF561__)

	// Pseudo TWI Configuration	to access video encoder/decoder registers
	// Run TWI clock at 100MHz & 50% Duty Cycle
	adi_twi_bit_rate rate={100,50};

	ADI_DEV_CMD_VALUE_PAIR TWIConfig[]={	// configuration table for the TWI driver
		{ ADI_TWI_CMD_SET_PSEUDO,			(void *)(&port)					},
		{ ADI_DEV_CMD_SET_DATAFLOW_METHOD,	(void *)ADI_DEV_MODE_SEQ_CHAINED},
		{ ADI_TWI_CMD_SET_FIFO,				(void *)0x0000					},
		{ ADI_TWI_CMD_SET_RATE,				(void *)(&rate)					},
		{ ADI_TWI_CMD_SET_LOSTARB,			(void *)1						},
		{ ADI_TWI_CMD_SET_ANAK,				(void *)0						},
		{ ADI_TWI_CMD_SET_DNAK,				(void *)0						},
		{ ADI_DEV_CMD_SET_DATAFLOW,			(void *)TRUE					},
		{ ADI_DEV_CMD_END,					NULL							}
	};                	        

#else
#error "*** ERROR: Application doesnot support this processor yet ***"
#endif

/**************************************
ADV717x Register Configuration Tables
**************************************/

    // ADV717x register configuration table for PAL mode
    ADI_DEV_ACCESS_REGISTER ADV717x_PAL_Cfg[]={
        					{ADV717x_MR0,	0x05},		// register address, configuration data
    					   	{ADV717x_MR1,	0x10},
    					   	{ADV717x_MR2,	0x00},
    					   	{ADV717x_MR3,	0x00},
    					   	{ADV717x_MR4,	0x00},
    					   	{ADV717x_TMR0, 	0x08}, 
    					   	{ADV717x_TMR1, 	0x00},
    					   	{ADI_DEV_REGEND,0	}};		// End of register access
    					   	
    // ADV717x register configuration table for NTSC mode
    ADI_DEV_ACCESS_REGISTER ADV717x_NTSC_Cfg[]={
        					{ADV717x_MR0, 	0x00},		// register address, configuration data
    					   	{ADV717x_MR1, 	0x58},
    					   	{ADV717x_MR2, 	0x00},
    					   	{ADV717x_MR3, 	0x00},
    					   	{ADV717x_MR4, 	0x10},
    					   	{ADV717x_TMR0, 	0x00}, 
    					   	{ADV717x_TMR1, 	0x00},
    					   	{ADI_DEV_REGEND,0	}};		// End of register access    					   	

	// Video Encoder configuration table
	ADI_DEV_CMD_VALUE_PAIR VideoEncoderConfigTable [] = {	
		{ ADI_ADV717x_CMD_SET_TWI_CONFIG_TABLE,	(void *) TWIConfig						},	// TWI Configuration used for video encoder
// Set PPI Device number for video out
#if defined(__ADSPBF561__)
		{ ADI_ADV717x_CMD_SET_PPI_DEVICE_NUMBER,(void *) 1								},	// BF561 - PPI 1 used for Video out
#else
		{ ADI_ADV717x_CMD_SET_PPI_DEVICE_NUMBER,(void *) 0								},	// BF533 has only PPI 0
#endif		
		{ ADI_DEV_CMD_END,						NULL									},
	};

	// Video Decoder configuration table (leave the video format to default setting (NTSC))
	ADI_DEV_CMD_VALUE_PAIR VideoDecoderConfigTable [] = {	
		{ ADI_AD7183_CMD_SET_TWI_CONFIG_TABLE,	(void *) TWIConfig						},	// TWI Configuration used for video decoder
		{ ADI_AD7183_CMD_OPEN_PPI, 				(void *) 0								},	// Open PPI device for video in
		{ ADI_DEV_CMD_END,						NULL									},
	};



/*********************************************************************

    Function:       install_system_services

    Description:    Initialises EZ kit and system services

*********************************************************************/
// function implementations
section("sdram_bank1")
void InstallSystemServices(void)
{
	u32 ResponseCount;			// response counter
	u32 mdIVG,ppiIVG; 

	/* initialize the ezKit power,EBIU,DMA....*/
	adi_ssl_Init();
	
	ezInit(1);	

	ezErrorCheck(adi_int_CECHook(3, ExceptionHandler, NULL, FALSE));
	ezErrorCheck(adi_int_CECHook(5, HWErrorHandler, NULL, FALSE));

	ezErrorCheck(adi_dcb_Open(14, &DCBMgrData[ADI_DCB_QUEUE_SIZE], (ADI_DCB_ENTRY_SIZE)*6, &ResponseCount, &DCBManagerHandle));

	ezTurnOffAllLEDs ();	// Turn off all LEDs

	/*** Initialise flags corresponding to the Ez-Kit buttons ***/
	// Initialise the Termination button
	InitButton(TERMINATE_BUTTON);
	
#if defined(__ADSPBF561__)
	// Initialise the Update video mode button system status flag
	InitButton(UPDATE_VIDEO_MODE_BUTTON);
	// Clear Update Video Mode button 
	PBFlag.Video_Mode = FALSE;	
	// Initialise the Pause video button
	InitButton(PAUSE_FRAME_CAPTURE_BUTTON);	
#elif defined(__ADSPBF533__)
#if !defined(VIDEO_IN_SLIDE_SHOW)	// Conditional compilation macro to enable slide show mode
	// Initialise the Frame capture video button only when slide show mode is disabled
	InitButton(PAUSE_FRAME_CAPTURE_BUTTON);
	// Clear Frame capture button system status flag
	PBFlag.Frame_Capture = FALSE;
#endif
#endif	


	// Initialise the toggle display button
	InitButton(TOGGLE_DISPLAY_BUTTON);
	// Clear Toggle display button system status flag
	PBFlag.Toggle_Display= FALSE;
	

				
	SystemFlag.SobelDone			= TRUE;		// Mark sobel flag as done to start sobel conversion
	SystemFlag.SobelEnable			= TRUE;		// Enable sobel out
	SystemFlag.UpdateVideoMode		= FALSE;	// clear update video mode flag
	SystemFlag.Pause_Frame_Capture	= FALSE;	// clear pause video/frame capture flag	
	SystemFlag.FieldcopyDone		= FALSE;	// clear field copy done flag
	SystemFlag.UpdateVideoInBufs	= FALSE;	// clear buffer update flag (video in callback)
	SystemFlag.UpdateVideoOutBufs	= FALSE;	// clear buffer update flag (video out callback)
	pPausedBuffer 					= NULL;		// pointer to paused video 2D buffer
	ADV717xDeviceHandle				= NULL;		// clear ADV717xDeviceHandle to indicate this is a cold start
	

	return;
}

/*********************************************************************

    Function:       InitButton

    Description:    Initialises Blackfin Flags connected to
    				EZ-kit buttons

*********************************************************************/	
section("sdram_bank1")
void InitButton (
	ADI_FLAG_ID	FlagID
){
	int Result;
	
    // open the flag    
    ezErrorCheck(adi_flag_Open (FlagID));
    // set flag direction as input
    ezErrorCheck(adi_flag_SetDirection(FlagID,ADI_FLAG_DIRECTION_INPUT));    
    // set flag trigger to sense button press & generate callback
    // senses on falling edge
    Result = adi_flag_InstallCallback	(	FlagID,							// Flag ID
#if defined(__ADSPBF561__)    
    											ADI_INT_PF0_15_A,				// peripheral ID
#elif defined(__ADSPBF533__)
												ADI_INT_PFA,					// peripheral ID
#endif												
    											ADI_FLAG_TRIGGER_RISING_EDGE,	// flag trigger mode
    											FALSE,							// not a wakeup flag
    											(void *)FlagID,					// Flag ID as client handle
    											DCBManagerHandle,				// Callback Manager
    											ButtonPressCallback				// callback function    						
    										);
	if (Result != 0)
	{
		printf("%x\n",Result);
		ezErrorCheck(Result);
	}
	    										
    										
    
	return;
}    

/*********************************************************************

	Function:		TerminateSystem

	Description:	Closes all devices and terminates the application

*********************************************************************/
section("sdram_bank1")
void TerminateSystem (void)
{
	// Close MDMA streams
    CloseMDMA_Streams ();
    
#if defined(__ADSPBF561__)
	  
   	// Close ADV7183
	ezErrorCheck(adi_dev_Close(ADV7183DeviceHandle));
	// Close ADV717x
	ezErrorCheck(adi_dev_Close(ADV717xDeviceHandle));
	
#endif

	adi_ssl_Terminate();
	return;		
}

/*********************************************************************

    Function:       InstallVideoDecoder
    Description:    Installs Video Decoder (ADV7183)

*********************************************************************/
section("sdram_bank1")
void InstallVideoDecoder()	
{
	u32 Result;
	
	// For BF533 pull the video decoder from reset mode
     // enable video decoder (7183)
    ezEnableVideoDecoder();
    // delay to stabilise 7183
#if defined(__ADSPBF533__)

    ezDelay(ADV7183_DELAY);

#endif	
    // open the ADV7183 driver for video input
   	ezErrorCheck(adi_dev_Open(  adi_dev_ManagerHandle,     		// Dev manager Handle
               		   			&ADIADV7183EntryPoint,          // Device Entry point
                          		0,                              // Device number
	                            NULL,                           // No client handle
   		                        &ADV7183DeviceHandle,           // Device manager handle address
       		                    ADI_DEV_DIRECTION_INBOUND,      // Data Direction (video in)
           		                adi_dma_ManagerHandle,               // Handle to DMA Manager
               		            DCBManagerHandle,				// Callback Manager
                   		        VideoInCallback));				// callback function

	// Configure the video decoder device driver
	//ezErrorCheck(adi_dev_Control(ADV7183DeviceHandle, ADI_DEV_CMD_TABLE, VideoDecoderConfigTable));
	Result = adi_dev_Control(ADV7183DeviceHandle,ADI_AD7183_CMD_SET_TWI_CONFIG_TABLE,(void *) TWIConfig); 
	if(Result!= 0)
	printf("ADI_AD7183_CMD_SET_TWI_CONFIG_TABLE failed %x\n",Result);
	
#if defined(__ADSPBF561__)	
	// check if this is a cold start
	if (ADV717xDeviceHandle == NULL)
	{
#endif
		// if so, then Update Video Input Mode
		UpdateVideoMode ();
		// clear UpdateVideo flag	
		SystemFlag.UpdateVideoFlag = FALSE;
		// Format the Sobel video out frame buffers to specified video mode				
		FormatVideoOutFrames();
		// Configure and Install MDMA for Sobel Edge Detection
		ConfigureMDMA();
		
#if defined(__ADSPBF561__)			
	}
#endif

	// open the AD7183-PPI device 0 (see Schematic)
	Result =  adi_dev_Control(ADV7183DeviceHandle, ADI_AD7183_CMD_OPEN_PPI, (void *)0);
	if(Result!=0)
	printf("ADI_AD7183_CMD_OPEN_PPI failed %x\n",Result);

	// Check video mode
	if (SystemFlag.ITU656_Mode == ITU656_PAL)
	{
	    // Config ADV7183 in PAL mode
		Result = adi_dev_Control(ADV7183DeviceHandle, ADI_AD7183_CMD_SET_VIDEO_FORMAT, (void *)1);
	}	
	else	// Video must be in NTSC
	{
	    // Config ADV7183 in NTSC mode
		Result = adi_dev_Control(ADV7183DeviceHandle, ADI_AD7183_CMD_SET_VIDEO_FORMAT, (void *)0);
	}
	
	if(Result!=0)
	printf("ADI_AD7183_CMD_SET_VIDEO_FORMAT failed %x\n",Result);
		
#if defined(__ADSPBF561__)
	// Set Dataflow method
	ezErrorCheck(adi_dev_Control(ADV7183DeviceHandle, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *) ADI_DEV_MODE_CHAINED_LOOPBACK));
	// Enable streaming
	ezErrorCheck(adi_dev_Control(ADV7183DeviceHandle, ADI_DEV_CMD_SET_STREAMING, (void *) TRUE));
#else
	// Set Dataflow method
	Result = adi_dev_Control(ADV7183DeviceHandle, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *) ADI_DEV_MODE_CHAINED);	
	if (Result != 0)
	{
		printf("7183 CMD_SET_DATAFLOW_METHOD failed %x\n",Result);
		ezErrorCheck(Result);
	}
#endif
	
	// Prepare and submit video input buffer(s)
	SubmitVideoInBuffers();	
				
				
	return;
}

/*********************************************************************

    Function:       EnableVideoIn
    Description:    Enable/Disable Video in dataflow (ADV7183)

*********************************************************************/
section("sdram_bank1")
void EnableVideoIn (bool dataflow)
{
	Result = adi_dev_Control(ADV7183DeviceHandle, ADI_DEV_CMD_SET_DATAFLOW, (void*)dataflow);
	if (Result != 0)
	{
		printf("7183 CMD_SET_DATAFLOW failed %x\n",Result);
		ezErrorCheck(Result);
	}


}

/*********************************************************************

    Function:       InstallVideoEncoder
    Description:    Installs Video Encoder (ADV717x)

*********************************************************************/
section("sdram_bank1")
void InstallVideoEncoder()	
{

	ezEnableVideoEncoder();// enable the video encoder (7171)
	
#if defined(__ADSPBF561__)

    // open the ADV7171 driver for video output
   	ezErrorCheck(adi_dev_Open(  adi_dev_ManagerHandle,     		// Dev manager Handle
                		   		&ADIADV7179EntryPoint,          // Device Entry point
                            	0,                              // Device number
	                            NULL,                           // No client handle
    	                        &ADV717xDeviceHandle,           // Device manager handle address
        	                    ADI_DEV_DIRECTION_OUTBOUND,     // Data Direction (video out)
            	                adi_dma_ManagerHandle,               // Handle to DMA Manager
                	            DCBManagerHandle,				// Callback Manager
                    	        VideoOutCallback));				// callback function
                    	        
#elif defined(__ADSPBF533__)

    // open the AD7179 driver for video output
    ezErrorCheck(adi_dev_Open(  adi_dev_ManagerHandle,            // Dev manager Handle
                 		   		&ADIADV7171EntryPoint,          // Device Entry point
                            	0,                              // Device number
	                            NULL,                           // No client handle
    	                        &ADV717xDeviceHandle,           // Device manager handle address
        	                    ADI_DEV_DIRECTION_OUTBOUND,     // Data Direction (video out)
            	                adi_dma_ManagerHandle,               // Handle to DMA Manager
                	            DCBManagerHandle,      			// Callback Manager
                    	        VideoOutCallback));				// callback function

#else
#error "*** ERROR: Processor not yet supported by the drivers ***"
#endif

	// Configure the video encoder device driver
	Result = adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_TABLE, VideoEncoderConfigTable);	
	if (Result != 0)
	{
		printf("7183 DEV_CMD_TABLE failed %x\n",Result);
		ezErrorCheck(Result);
	}

	// Open PPI device for video out
	ezErrorCheck(adi_dev_Control(ADV717xDeviceHandle, ADI_ADV717x_CMD_SET_PPI_STATUS, (void *)ADI_ADV717x_PPI_OPEN));	
	
	// Update ADV717x Operating video mode
	UpdateADV717xVideoMode ();	


	// Set Dataflow method
	Result = adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_SET_DATAFLOW_METHOD, (void *) ADI_DEV_MODE_CHAINED_LOOPBACK);
	if (Result != 0)
	{
		printf("717x CMD_SET_DATAFLOW_METHOD failed %x\n",Result);
		ezErrorCheck(Result);
	}
	
	#if defined(__ADSPBF561__)	
	// Enable streaming
	ezErrorCheck(adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_SET_STREAMING, (void *) TRUE));
#elif defined(__ADSPBF533__)
	// Prepare and submit video input buffer(s)
	SubmitVideoOutBuffers();			
#endif

		
	return;
}

/*********************************************************************

    Function:       UpdateADV717xVideoMode
    Description:    Updates ADV717x operating video mode

*********************************************************************/
section("sdram_bank1")
void	UpdateADV717xVideoMode (void)	
{
    // Check present ITU video mode
	if (SystemFlag.ITU656_Mode == ITU656_PAL)
	{
	    // Config ADV717x in PAL mode
	    // SCFR with PAL config values
		Result = adi_dev_Control(ADV717xDeviceHandle, ADI_ADV717x_CMD_SET_SCF_REG, (void *)ADV717x_SCF_VALUE_PAL_BI);
		if (Result != 0)
		{
			printf("717x_CMD_SET_SCF_REG(PAL) failed %x\n",Result);
			ezErrorCheck(Result);
		}

		// Config other internal regs of ADV717x to PAL
		Result = adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)ADV717x_PAL_Cfg);
		if (Result != 0)
		{
			printf("717x_CMD_REGISTER_TABLE_WRITE failed %x\n",Result);
			ezErrorCheck(Result);
		}

	}	
	else	// Video must be in NTSC
	{
	    // Config ADV717x in NTSC mode
	    // SCFR with NTSC config values
		Result = adi_dev_Control(ADV717xDeviceHandle, ADI_ADV717x_CMD_SET_SCF_REG, (void *)ADV717x_SCF_VALUE_NTSC);
		if (Result != 0)
		{
			printf("717x_CMD_SET_SCF_REG(NTSC) failed %x\n",Result);
			ezErrorCheck(Result);
		}

		// Config other internal regs of ADV717x to NTSC
		Result = adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)ADV717x_NTSC_Cfg);
		if (Result != 0)
		{
			printf("717x_CMD_REGISTER_TABLE_WRITE failed %x\n",Result);
			ezErrorCheck(Result);
		}

	}
	


	return;
}	
	
/*********************************************************************

    Function:       EnableVideoOut
    Description:    Enable/Disable Video out dataflow (ADV717x)

*********************************************************************/
section("sdram_bank1")
void EnableVideoOut (bool dataflow)
{
	ezErrorCheck(adi_dev_Control(ADV717xDeviceHandle, ADI_DEV_CMD_SET_DATAFLOW, (void*)dataflow));
}

/*********************************************************************

	Function:		ExceptionHandler
					HWErrorHandler

	Description:	We should never get an exception or hardware error,
					but just in case we'll catch them and simply turn
					on all the LEDS should one ever occur.

*********************************************************************/
section("sdram_bank1")
static ADI_INT_HANDLER(ExceptionHandler)	// exception handler
{
		ezErrorCheck(1);
		return(ADI_INT_RESULT_PROCESSED);
}

section("sdram_bank1")
static ADI_INT_HANDLER(HWErrorHandler)		// hardware error handler
{
		ezErrorCheck(1);
		return(ADI_INT_RESULT_PROCESSED);
}

/*********************************************************************

    Function:       VideoOutCallback

    Description:    Video Out callback function (ADV717x)

*********************************************************************/
section ("Callback_Code_L1")
static void VideoOutCallback(
	void *AppHandle,
	u32  Event,
	void *pArg
){         
	// Call corresponding service routine   
	VideoOut(AppHandle,Event,pArg);
	return;
}

/*********************************************************************

    Function:       VideoInCallback

    Description:    Video In callback function (ADV7183)

*********************************************************************/
section ("Callback_Code_L1")
static void VideoInCallback(
	void *AppHandle,
	u32  Event,
	void *pArg
){
	// Call corresponding service routine   
	VideoIn(AppHandle,Event,pArg);
}

/*********************************************************************

    Function:       ButtonPressCallback

    Description:    Ez-Kit button press callback function
    				Corresponding push button related operations
    				will start only after the button is released

*********************************************************************/
section ("Callback_Code_L1")
static void ButtonPressCallback	(	
	void *AppHandle,
	u32  Event,
	void *pArg
){
	// Call corresponding service routine   
	ButtonPressed(AppHandle,Event,pArg);
}

/*****/
