/******************************************************************************

Copyright (c) 2005 Analog Devices.  All Rights Reserved.

This software is proprietary and confidential.  By using this software you agree
to the terms of the associated Analog Devices License Agreement.  

******************************************************************************/



/******************************************************************************

$File:		common.c $
$Revision: 1.3 $
$Date: 2008/03/24 20:03:52 $


Description:
	Common sensor functions
	

Modification History:
====================
Revision 1.0 - BJ 2006/07/11
	Created file
	
******************************************************************************/



/******************************************************************************

Include files

******************************************************************************/

#include <SensorCommon/common.h>
#include <ada_gfx/imageprocess.h>




/******************************************************************************

	Function: ImageCopy
	
	Description: Copy an input image and overlay to an output image. If input
		is empty then only the overlay will by copied, if overlay is null then
		only input image will be copied.

******************************************************************************/

u32 ImageCopy(
	unsigned char Frame, DEVICE_TYPE Type, GFX_MODE Mode,
	ADI_DEV_BUFFER *Input, ADI_DEV_BUFFER *Output,
	GFX_CANVAS *Overlay, u32 Transparent)
{
	typedef struct
	{
		u32 *Data;
		u32 Width,Height;
		u32 FrameWidth,FrameHeight;
	} ImageInfo;
	
	static u32 OutData[GFX_PAL_FRAME_WIDTH],Blank[GFX_PAL_FRAME_WIDTH];
	
	ImageInfo In,Out;
	u32 f,x,y,j,*OverlayData,OutFrameOffset,InFrameOffset;
	ADI_IMAGE_PROCESS_CALLBACK_FN Func;
	
	
	if (!Output) return ADI_DEV_RESULT_FAILED;
	
	
	Out.Data=(u32 *)Output->TwoD.Data;
	Out.Width=(Output->TwoD.XCount*Output->TwoD.ElementWidth)/sizeof(Out.Data[0]);
	Out.Height=Output->TwoD.YCount;
	OverlayData=(u32 *)Overlay->Data;
	
	
	Func=Mode==GFX_MODE_VGA?ImageProcess_rgb2rgb:ImageProcess_yuv2yuv;
	switch (Mode)
	{
		case GFX_MODE_VGA:
			OverlayData+=GFX_VGA_FRAME_WIDTH*GFX_VGA_TOP/2;
			Out.Data+=GFX_VGA_FRAME_WIDTH*GFX_VGA_TOP/2;
			Out.FrameWidth=Out.Width;
			Out.FrameHeight=Out.Height;
			Out.Height-=GFX_VGA_TOP+GFX_VGA_BOTTOM;
			switch (Type)
			{
				case DEVICE_OV7648: Func=ImageProcess_rgb2rgb; break;
				case DEVICE_MT9V022M: Func=ImageProcess_grey2rgb; break;
			}
			OutFrameOffset=-Out.FrameWidth*(Out.Height-1);
			Out.FrameWidth*=2;
			break;
		
		
		case GFX_MODE_NTSCI:
			OverlayData+=(GFX_NTSC_LEFT+(GFX_NTSC_FRAME_WIDTH*GFX_NTSC_TOP))/2;
			Out.Data+=(GFX_NTSC_LEFT+(GFX_NTSC_FRAME_WIDTH*GFX_NTSC_TOP))/2;
			Out.FrameWidth=Out.Width;
			Out.Width-=(GFX_NTSC_LEFT+GFX_NTSC_RIGHT)/2;
			Out.Height-=GFX_NTSC_TOP+GFX_NTSC_BOTTOM;
			Out.FrameHeight=Out.Height;
			switch (Type)
			{
				case DEVICE_OV7648: Func=ImageProcess_yuv2yuv; break;
				case DEVICE_MT9V022M: Func=ImageProcess_grey2yuv; break;
			}
			OutFrameOffset=Out.FrameWidth*GFX_NTSC_BOTTOM;
			break;
		
		
		case GFX_MODE_PALI:
			OverlayData+=(GFX_PAL_LEFT+(GFX_PAL_FRAME_WIDTH*GFX_PAL_TOP))/2;
			Out.Data+=(GFX_PAL_LEFT+(GFX_PAL_FRAME_WIDTH*GFX_PAL_TOP))/2;
			Out.FrameWidth=Out.Width;
			Out.Width-=(GFX_PAL_LEFT+GFX_PAL_RIGHT)/2;
			Out.Height-=GFX_PAL_TOP+GFX_PAL_BOTTOM;
			Out.FrameHeight=Out.Height;
			switch (Type)
			{
				case DEVICE_OV7648: Func=ImageProcess_yuv2yuv; break;
				case DEVICE_MT9V022M: Func=ImageProcess_grey2yuv; break;
			}
			OutFrameOffset=Out.FrameWidth*GFX_PAL_BOTTOM;
			break;
	}
	
	
	if (Input&&Type!=DEVICE_UNKNOWN)
	{
		In.Data=(u32 *)Input->TwoD.Data;
		In.Width=(Input->TwoD.XCount*Input->TwoD.ElementWidth)/sizeof(In.Data[0]);
		In.Height=Input->TwoD.YCount;
		In.FrameWidth=In.Width;
		In.FrameHeight=(Out.Height-In.Height)/2;
		
		
		switch (Mode)
		{
			case GFX_MODE_VGA:
				In.Data-=In.FrameHeight*In.Width;
				InFrameOffset=-In.FrameWidth*(Out.Height-1);
				In.FrameWidth*=2;
				break;
			
			
			case GFX_MODE_NTSCI:
			case GFX_MODE_PALI:
				In.Data-=In.FrameHeight*In.Width/2;
				InFrameOffset=-In.FrameWidth*(Out.Height-In.Height)/2;
		}
	} else
	{
		In.Data=NULL;
		In.Width=0;
		In.Height=0xFFFF;
		In.FrameWidth=0;
		In.FrameHeight=0;
	}
	
	Out.Height/=2;
	for (f=0;f<2;f++,
		Out.Data+=OutFrameOffset,
		OverlayData+=OutFrameOffset,
		In.Data+=InFrameOffset)
		if (Frame&(1<<f))
		{
			for (y=0,j=0x100000000-(In.FrameHeight/2);y<Out.Height;
				y++,j++,
				Out.Data+=Out.FrameWidth,
				OverlayData+=Out.FrameWidth,
				In.Data+=In.FrameWidth)
			{
				for (x=0;x<Out.Width;x++) OutData[x]=OverlayData[x];
				if (j<In.Height/2) Func(In.Width,In.Data,Out.Width,OutData,Transparent);
				
				if (Frame!=3)
					for (x=0;x<Out.Width;x++)
					{
						u32 i;
						Out.Data[x]=OutData[x];
						for (i=10;i;i--) asm("nop;");
					}
				else for (x=0;x<Out.Width;x++) Out.Data[x]=OutData[x];
			}
		} else
		{
			Out.Data+=Out.FrameWidth*Out.Height;
			OverlayData+=Out.FrameWidth*Out.Height;
			In.Data+=In.FrameWidth*Out.Height;\
		}
	return ADI_DEV_RESULT_SUCCESS;
}

/*****************************************************************************/
