
/*
#include <stdio.h>
#include <Arduino.h>
#include <EEPROM.h>
#include <SPI.h>
#include <avr/pgmspace.h>
*/



/* Sample application to demonstrat FT800 primitives, widgets and customized screen shots */

#include "FT_Platform.h"
#include "FT_RotaryDial.h"
#include "FT_Font_Table.h"


//#define SAMAPP_DISPLAY_WQVGA 1
//#define SAMAPP_DISPLAY_QVGA	 1


#define SAMAPP_DELAY_BTW_APIS (1000)
#define SAMAPP_ENABLE_DELAY() Ft_Gpu_Hal_Sleep(SAMAPP_DELAY_BTW_APIS)
#define SAMAPP_ENABLE_DELAY_VALUE(x) Ft_Gpu_Hal_Sleep(x)
#define BLK_LEN	  1024

#define CLOCK_HANDLE	(0x01)

#define DIAL		1

ft_int32_t BaseTrackVal = 0,BaseTrackValInit = 0,BaseTrackValSign = 0;
/* Global variables for display resolution to support various display panels */
/* Default is WQVGA - 480x272 */
#ifdef SAMAPP_DISPLAY_WQVGA	
ft_int16_t FT_DispWidth = 480;
ft_int16_t FT_DispHeight = 272;
ft_int16_t FT_DispHCycle =  548;
ft_int16_t FT_DispHOffset = 43;
ft_int16_t FT_DispHSync0 = 0;
ft_int16_t FT_DispHSync1 = 41;
ft_int16_t FT_DispVCycle = 292;
ft_int16_t FT_DispVOffset = 12;
ft_int16_t FT_DispVSync0 = 0;
ft_int16_t FT_DispVSync1 = 10;
ft_uint8_t FT_DispPCLK = 5;
ft_char8_t FT_DispSwizzle = 0;
ft_char8_t FT_DispPCLKPol = 1;
#endif


const ft_uint8_t FT_DLCODE_BOOTUP[12] = 
{
    0,255,0,2,//GPU instruction CLEAR_COLOR_RGB
    7,0,0,38, //GPU instruction CLEAR
    0,0,0,0,  //GPU instruction DISPLAY
};


/* Global used for buffer optimization */
Ft_Gpu_Hal_Context_t host,*phost;


ft_uint32_t Ft_CmdBuffer_Index;
ft_uint32_t Ft_DlBuffer_Index;

#ifdef BUFFER_OPTIMIZATION
ft_uint8_t  Ft_DlBuffer[FT_DL_SIZE];
ft_uint8_t  Ft_CmdBuffer[FT_CMD_FIFO_SIZE];
#endif

ft_void_t Ft_App_WrCoCmd_Buffer(Ft_Gpu_Hal_Context_t *phost,ft_uint32_t cmd)
{
#ifdef  BUFFER_OPTIMIZATION
   /* Copy the command instruction into buffer */
   ft_uint32_t *pBuffcmd;
   pBuffcmd =(ft_uint32_t*)&Ft_CmdBuffer[Ft_CmdBuffer_Index];
   *pBuffcmd = cmd;
#endif
#ifdef ARDUINO_PLATFORM
   Ft_Gpu_Hal_WrCmd32(phost,cmd);
#endif

   /* Increment the command index */
   Ft_CmdBuffer_Index += FT_CMD_SIZE;  
}

ft_void_t Ft_App_WrDlCmd_Buffer(Ft_Gpu_Hal_Context_t *phost,ft_uint32_t cmd)
{
#ifdef BUFFER_OPTIMIZATION  
   /* Copy the command instruction into buffer */
   ft_uint32_t *pBuffcmd;
   pBuffcmd =(ft_uint32_t*)&Ft_DlBuffer[Ft_DlBuffer_Index];
   *pBuffcmd = cmd;
#endif

#ifdef ARDUINO_PLATFORM
   Ft_Gpu_Hal_Wr32(phost,(RAM_DL+Ft_DlBuffer_Index),cmd);
#endif
   /* Increment the command index */
   Ft_DlBuffer_Index += FT_CMD_SIZE;  
}

ft_void_t Ft_App_WrCoStr_Buffer(Ft_Gpu_Hal_Context_t *phost,const ft_char8_t *s)
{
#ifdef  BUFFER_OPTIMIZATION  
  ft_uint16_t length = 0;
  length = strlen(s) + 1;//last for the null termination
  
  strcpy(&Ft_CmdBuffer[Ft_CmdBuffer_Index],s);  

  /* increment the length and align it by 4 bytes */
  Ft_CmdBuffer_Index += ((length + 3) & ~3);  
#endif  
}

ft_void_t Ft_App_Flush_DL_Buffer(Ft_Gpu_Hal_Context_t *phost)
{
#ifdef  BUFFER_OPTIMIZATION    
   if (Ft_DlBuffer_Index > 0)
     Ft_Gpu_Hal_WrMem(phost,RAM_DL,Ft_DlBuffer,Ft_DlBuffer_Index);
#endif     
   Ft_DlBuffer_Index = 0;
   
}

ft_void_t Ft_App_Flush_Co_Buffer(Ft_Gpu_Hal_Context_t *phost)
{
#ifdef  BUFFER_OPTIMIZATION    
   if (Ft_CmdBuffer_Index > 0)
     Ft_Gpu_Hal_WrCmdBuf(phost,Ft_CmdBuffer,Ft_CmdBuffer_Index);
#endif     
   Ft_CmdBuffer_Index = 0;
}

#ifdef SAMAPP_ENABLE_ROTARY_DEMO
FT_PROGMEM ft_prog_uint16_t sintab[] = {
0, 402, 804, 1206, 1607, 2009, 2410, 2811, 3211, 3611, 4011, 4409, 4807, 5205, 5601, 5997, 6392, 
6786, 7179, 7571, 7961, 8351, 8739, 9126, 9511, 9895, 10278, 10659, 11038, 11416, 11792, 12166, 12539,
12909, 13278, 13645, 14009, 14372, 14732, 15090, 15446, 15799, 16150, 16499, 16845, 17189, 17530, 17868,
18204, 18537, 18867, 19194, 19519, 19840, 20159, 20474, 20787, 21096, 21402, 21705, 22004, 22301, 22594, 
22883, 23169, 23452, 23731, 24006, 24278, 24546, 24811, 25072, 25329, 25582, 25831, 26077, 26318, 26556, 26789, 
27019, 27244, 27466, 27683, 27896, 28105, 28309, 28510, 28706, 28897, 29085, 29268, 29446, 29621, 29790, 29955, 
30116, 30272, 30424, 30571, 30713, 30851, 30984, 31113, 31236, 31356, 31470, 31580, 31684, 31785, 31880, 31970, 
32056, 32137, 32213, 32284, 32350, 32412, 32468, 32520, 32567, 32609, 32646, 32678, 32705, 32727, 32744, 32757, 
32764, 32767, 32764};

ft_int16_t SAMAPP_qsin(ft_uint16_t a)
{
  ft_uint8_t f;
  ft_int16_t s0,s1;

  if (a & 32768)
    return -SAMAPP_qsin(a & 32767);
  if (a & 16384)
      a = 32768 - a;
  f = a & 127;
  s0 = ft_pgm_read_word(sintab + (a >> 7));
  s1 = ft_pgm_read_word(sintab + (a >> 7) + 1);
  return (s0 + ((ft_int32_t)f * (s1 - s0) >> 7));
}

/* cos funtion */
ft_int16_t SAMAPP_qcos(ft_uint16_t a)
{
  return (SAMAPP_qsin(a + 16384));
}
#endif



/* API to demonstrate calibrate widget/functionality */
ft_void_t SAMAPP_CoPro_Widget_Calibrate()
{
	ft_uint8_t *pbuff;
	ft_uint32_t NumBytesGen = 0,TransMatrix[6];
	ft_uint16_t CurrWriteOffset = 0;

	/*************************************************************************/
	/* Below code demonstrates the usage of calibrate function. Calibrate    */
	/* function will wait untill user presses all the three dots. Only way to*/
	/* come out of this api is to reset the coprocessor bit.                 */
	/*************************************************************************/
	{

	Ft_Gpu_CoCmd_Dlstart(phost);

	Ft_App_WrCoCmd_Buffer(phost,CLEAR_COLOR_RGB(64,64,64));
	Ft_App_WrCoCmd_Buffer(phost,CLEAR(1,1,1));
	Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0xff,0xff,0xff));
	/* Draw number at 0,0 location */
	//Ft_App_WrCoCmd_Buffer(phost,COLOR_A(30));
	Ft_Gpu_CoCmd_Text(phost,(FT_DispWidth/2), (FT_DispHeight/2), 27, OPT_CENTER, "Please Tap on the dot");
	Ft_Gpu_CoCmd_Calibrate(phost,0);

	/* Download the commands into FIFIO */
	Ft_App_Flush_Co_Buffer(phost);
	/* Wait till coprocessor completes the operation */
	Ft_Gpu_Hal_WaitCmdfifo_empty(phost);
	/* Print the configured values */
	Ft_Gpu_Hal_RdMem(phost,REG_TOUCH_TRANSFORM_A,(ft_uint8_t *)TransMatrix,4*6);//read all the 6 coefficients
#ifdef MSVC_PLATFORM
	printf("Touch screen transform values are A 0x%x,B 0x%x,C 0x%x,D 0x%x,E 0x%x, F 0x%x",
		TransMatrix[0],TransMatrix[1],TransMatrix[2],TransMatrix[3],TransMatrix[4],TransMatrix[5]);
#endif
	}

}


static void polarxy(ft_uint32_t r, ft_uint16_t th, ft_uint16_t *x, ft_uint16_t *y,ft_uint16_t ox,ft_uint16_t oy)
{
	//	th = th * 32768 / 180;
		*x = (16 * ox + (((long)r * SAMAPP_qsin(th)) >> 11) + 16);
		*y = (16 * oy - (((long)r * SAMAPP_qcos(th)) >> 11));
}
ft_uint16_t da(ft_int32_t i)
{
//  return (45) * (16384) / 180;
	return (i+90) * 65536 / 360;
}


ft_uint32_t Load_RawDataFromfile(ft_uchar8_t ImageArrayname[],/* Image Array*/
								 ft_uint32_t ptr,/* Array Size*/
								 ft_uint32_t RamAddr,
								 ft_int16_t Handle,
								 ft_int16_t Format,
								 ft_int16_t Stride,
								 ft_int16_t Width,
								 ft_int16_t Height,
								 ft_uint8_t i
								 )
{
	
	ft_int32_t fsize=0;
	fsize = SAMAPP_Uncompressed_FileSize[i];

        RamAddr = (ft_uint32_t)(RamAddr + 7) & (~7);
	Ft_Gpu_Hal_WrCmd32(phost,  CMD_INFLATE);
	Ft_Gpu_Hal_WrCmd32(phost,  RamAddr);

#ifdef MSVC_PLATFORM 
        Ft_Gpu_Hal_WrCmdBuf(phost,ImageArrayname,ptr);
#endif
#ifdef ARDUINO_PLATFORM
	Ft_Gpu_Hal_WrCmdBufFromFlash(phost,ImageArrayname,ptr);
#endif

	Ft_App_WrCoCmd_Buffer(phost,BITMAP_HANDLE(Handle));
	Ft_App_WrCoCmd_Buffer(phost,BITMAP_SOURCE(RamAddr));
	Ft_App_WrCoCmd_Buffer(phost, BITMAP_LAYOUT(Format,Stride,Height));		
	Ft_App_WrCoCmd_Buffer(phost, BITMAP_SIZE(NEAREST,BORDER,BORDER,Width,Height));		
	Ft_App_WrCoCmd_Buffer(phost, VERTEX2II(0,0,Handle,0));				
		

	fsize = (fsize + 7) & (~7);//align the buffer to 8
	return (RamAddr + fsize);
}




ft_void_t Rotary_Dial_phone()
{
	ft_uint8_t ReadTag = 0,PrevTag = 0,StoreTag,flag =0, PrintTag=0,Tagcheck=0,FontWid = 0, FontHt = 0,Penup=0;
	ft_char8_t StringArray[31];	
	ft_uint32_t temp =0,tagval,PrevTh = 0,adjusting = 0, CurrTh=0;	
	ft_uint16_t OuterCircleRadius=0, InnerCircleRadius,CentreWhiteCircle,PrevTouch=0,VertexX, VertexY;
	ft_uint16_t ScreenWidthMid,ScreenHeightMid,FontPLaceX,FontPLaceY,SmallNumCircleRad, i,j,k=0,StartTheta,EndTheta,IncTheta;
	ft_uint16_t NoX,NoY,vX,MinTheta,MaxTheta,thresholdflag=0,ButHt, ButWid,FingerstopX,FingerstopY,th,theta;	
	ft_uint32_t RotaryTag=0;
        ft_int16_t NoTouch,Touch, NextTh=0;
	SAMAPP_RotaryDial_Bmps_t BmpBalls[40];
	
	ScreenWidthMid = FT_DispWidth/2;
	ScreenHeightMid = FT_DispHeight/2; 
      	
        ft_uint32_t time;

        
	

#ifdef SAMAPP_DISPLAY_WQVGA
	OuterCircleRadius = ScreenWidthMid/2 - 19;	
	InnerCircleRadius = OuterCircleRadius - 50;
	SmallNumCircleRad = InnerCircleRadius/2 - 8;
	FingerstopX = ScreenWidthMid + 56;
	FingerstopY = ScreenHeightMid + 17;
	NoX = FT_DispWidth/6;//80; //(ScreenWidthMid)-(ScreenWidthMid/2);
	NoY = FT_DispHeight - (FT_DispHeight - 7);//7;
	ButHt = ScreenHeightMid - 111;
	ButWid = FT_DispWidth - 160;
#endif

#ifdef SAMAPP_DISPLAY_QVGA
	OuterCircleRadius = ScreenWidthMid/2 + 5;	
	InnerCircleRadius = 30;
	SmallNumCircleRad = 13;
	FingerstopX = ScreenWidthMid + 42;
	FingerstopY = ScreenHeightMid +10;
	NoX = FT_DispWidth/6;//80; //(ScreenWidthMid)-(ScreenWidthMid/2);
	NoY = FT_DispHeight - (FT_DispHeight - 7);//7;
	ButHt = ScreenHeightMid - 95;
	ButWid = FT_DispWidth - 110;
#endif

	CentreWhiteCircle = InnerCircleRadius + ((OuterCircleRadius - InnerCircleRadius)/2);	
	VertexX = 0;
	VertexY = 0;	
	StartTheta = 50;
	EndTheta = 320;
	IncTheta = 30;
	NoTouch = -32768;
	MinTheta = 30;
	MaxTheta = 60;
	vX = ScreenWidthMid;
	StringArray[0] = '\0';
	tagval = 10;


	Ft_Gpu_Hal_WrCmd32(phost, CMD_MEMSET);
	Ft_Gpu_Hal_WrCmd32(phost, 0L);//starting address of memset
	Ft_Gpu_Hal_WrCmd32(phost, 55L);//value of memset
	Ft_Gpu_Hal_WrCmd32(phost,256*1024);


	/* set the vol to max */
	Ft_Gpu_Hal_Wr8(phost, REG_VOL_SOUND,0xFF);

	/* Calculation of balls offsets and rate */
	for(i=0;i<40;i++)
	{
		BmpBalls[i].xOffset = ft_random(FT_DispWidth);
		BmpBalls[i].yOffset = ft_random(FT_DispHeight);

		BmpBalls[i].xDiff = ft_random(16) - 8;
		BmpBalls[i].yDiff = ft_random(8) - 4;
	}
	
	/* Construction of starting screen shot, assign all the bitmap handles here */
	Ft_App_WrCoCmd_Buffer(phost, CMD_DLSTART);
	Ft_App_WrCoCmd_Buffer(phost,CLEAR_COLOR_RGB(255,255,255));
	Ft_App_WrCoCmd_Buffer(phost,CLEAR(1,1,1));
	
	/* track circles outside the while loop */
	for(theta=StartTheta;theta<=EndTheta ;theta+=IncTheta)			
	{	
		th = theta;		
		if(theta == StartTheta + IncTheta) tagval = 9;
		th = da(th);				
		Ft_Gpu_CoCmd_Track(phost,ScreenWidthMid, ScreenHeightMid, DIAL, DIAL, tagval);		
		tagval--;
	}
	
	/* Download the raw data into intended locations */
	{
		ft_uint32_t RamAddrOffest = RAM_G;
		Ft_App_WrCoCmd_Buffer(phost, BEGIN(BITMAPS));

                RamAddrOffest = Load_RawDataFromfile(FingerStop,SAMAPP_FingerStop_SIZE,RamAddrOffest,0,ARGB4,56*2,56,38,0);//finger stopper
		RamAddrOffest = Load_RawDataFromfile(Call,SAMAPP_CallIcon,RamAddrOffest,1,ARGB4,56*2,56,56,1);//reject button
		RamAddrOffest = Load_RawDataFromfile(CallCancel,SAMAPP_CallCancelIcon,RamAddrOffest,2,ARGB4,56*2,56,56,2);//call button
		RamAddrOffest = Load_RawDataFromfile(YellowBall20x20,SAMAPP_YellowBall_20x20,RamAddrOffest,3,ARGB4,20*2,20,20,3);//ball 20x20
		RamAddrOffest = Load_RawDataFromfile(YellowBall30x30,SAMAPP_YellowBall_30x30,RamAddrOffest,4,ARGB4,30*2,30,30,4);//ball 30x30
		RamAddrOffest = Load_RawDataFromfile(YellowBall40x40,SAMAPP_YellowBall_40x40,RamAddrOffest,5,ARGB4,40*2,40,40,5);//ball 40x40
		RamAddrOffest = Load_RawDataFromfile(YellowBall60x60,SAMAPP_YellowBall_60x60,RamAddrOffest,6,ARGB4,60*2,60,60,6);//ball 60x60

		Ft_App_WrCoCmd_Buffer(phost, END());
	}
	Ft_App_WrCoCmd_Buffer(phost,DISPLAY());
	Ft_Gpu_CoCmd_Swap(phost);

	/* Download the commands into fifo */
	Ft_App_Flush_Co_Buffer(phost);

	/* Wait till coprocessor completes the operation */
	Ft_Gpu_Hal_WaitCmdfifo_empty(phost);


	do{
		
		Ft_App_WrCoCmd_Buffer(phost, CMD_DLSTART);

		/*Points*/
		Ft_App_WrCoCmd_Buffer(phost, CLEAR_COLOR_RGB(237 ,186 ,17) ); // background color
		Ft_App_WrCoCmd_Buffer(phost,CLEAR(1,1,1));
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_SIZE(512,218));
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_XY(0,0));
		Ft_Gpu_CoCmd_Gradient(phost,0, 0, 0xEDBA11,0, FT_DispHeight, 0x82660A);
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_SIZE(512,512));
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_XY(0,218));
		Ft_Gpu_CoCmd_Gradient(phost,0, 0, 0x2B2205,0, 218, 0x82660A);
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_SIZE(512,512));
		Ft_App_WrCoCmd_Buffer(phost,SCISSOR_XY(0,0));
		//Ft_Gpu_CoCmd_Gradient(phost,0, 0, 0xEDBA11,0, FT_DispHeight, 0x82660A);

		/* Draw all the background bitmaps - balls with various resolutions */
		Ft_App_WrCoCmd_Buffer(phost,BEGIN(BITMAPS));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255 ,255 ,255)); // brown outside circle

//		for(i = 0;i<40;i++)
//		{
//			Ft_App_WrCoCmd_Buffer(phost,VERTEX2II(BmpBalls[i].xOffset,BmpBalls[i].yOffset,3+(i%4),0));
//			BmpBalls[i].xOffset += BmpBalls[i].xDiff;
//			BmpBalls[i].yOffset += BmpBalls[i].yDiff;
//
//			if(BmpBalls[i].xOffset < -80)
//			{
//				BmpBalls[i].xOffset = FT_DispWidth + 80;
//			}
//			else if(BmpBalls[i].xOffset > FT_DispWidth + 80)
//			{
//				BmpBalls[i].xOffset = -80;
//			}
//
//			if(BmpBalls[i].yOffset < -80)
//			{
//				BmpBalls[i].yOffset = FT_DispHeight + 80;
//			}
//			else if(BmpBalls[i].yOffset > FT_DispHeight + 80)
//			{
//				BmpBalls[i].yOffset = -80;
//			}
//		}

		BmpBalls[ft_random(40)].xDiff = ft_random(16) - 8;
		BmpBalls[ft_random(40)].yDiff = ft_random(8) - 4;

		Ft_App_WrCoCmd_Buffer(phost,POINT_SIZE(OuterCircleRadius * 16) );
		
		Ft_App_WrCoCmd_Buffer(phost,BEGIN(FTPOINTS));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(235 ,117 ,0)); // brown outside circle
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16 - 24,ScreenHeightMid*16 - 24));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0 ,0 ,0)); // brown outside circle
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16 + 24,ScreenHeightMid*16 + 24));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(128 ,64 ,0)); // brown outside circle
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16,ScreenHeightMid*16));
		

	
		Ft_App_WrCoCmd_Buffer(phost,POINT_SIZE((InnerCircleRadius) * 16) );
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(87 ,64 ,8)); // inner circle - light brown color
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16 - 24,ScreenHeightMid*16 - 24));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0 ,0 ,0)); // inner circle - light brown color
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16 + 24,ScreenHeightMid*16+24));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(204 ,151 ,16)); // inner circle - light brown color
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(ScreenWidthMid*16,ScreenHeightMid*16));
	


		i = 0;//font inside the white circles - start at 0
		tagval = 10;// tag for the white circles - decrementing tagvalue inside loop

	
		Touch = Ft_Gpu_Hal_Rd16(phost, REG_TOUCH_SCREEN_XY+2);
		Tagcheck = Ft_Gpu_Hal_Rd8(phost, REG_TOUCH_TAG);

                RotaryTag = Ft_Gpu_Hal_Rd32(phost,REG_TRACKER);
		ReadTag = RotaryTag & 0xff;
		
	
		if((PrevTouch&0x8000) && (0 == PrevTag))
		{
			BaseTrackValInit = (ft_int16_t)((RotaryTag >> 16) & 0xffff);
		}
		else
		{
			BaseTrackValInit = 0;
		}
                /* verify for the track value */
                if((Touch != NoTouch))
		{
			if((ReadTag >= 1) && (ReadTag <= 10))
			{
				CurrTh = (ft_int16_t)((RotaryTag >> 16) & 0xffff);
				if(adjusting!=0)
				{
					flag = 0;
					BaseTrackVal += (ft_int16_t)(CurrTh - PrevTh);
					BaseTrackValSign += (ft_int16_t)(CurrTh - PrevTh);
					/* handling of loopback */
					BaseTrackVal &= 0xffff;		
					
					NextTh = (ft_uint16_t)(BaseTrackValSign / 182);	
				
				} 
				PrevTh = CurrTh;
				adjusting = (RotaryTag & 0xff);
				PrintTag = ReadTag;
			
			}
		}
                else if(Touch == NoTouch)
                {
			BaseTrackVal=0;		
			flag = 1;
                        Penup = 1;
			if(adjusting != 0)
			{
				if(NextTh > 0 )
				{
					NextTh-=20;	
					Ft_Gpu_Hal_Wr8(phost, REG_VOL_SOUND,0xff);
					Ft_Gpu_Hal_Wr16(phost, REG_SOUND,0x51);
					Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
					MinTheta = 30;
					MaxTheta = 60;
					
				}
				else
				{ 
					
					NextTh = 0;
					if((PrintTag >= 1) && (PrintTag <= 10) && (thresholdflag ==1))
					{
						if (PrintTag == 10)PrintTag = 0;
						StringArray[k] = PrintTag + '0';
						
						if(k<26)
						{
							k++;							
						}
						else if (k == 26)
						{
							k = 0;
							StringArray[k] = PrintTag + '0';
							k++;
						}
						thresholdflag=0;
					}
					StringArray[k] = '\0';					
					adjusting = 0;
					
				}					
			}
			else if(adjusting == 0)
			{
				RotaryTag = '\0';
				PrintTag = '\0';			
				
			}
			BaseTrackValSign = 0;
		}
	
		Ft_App_WrCoCmd_Buffer(phost,BEGIN(FTPOINTS));
		Ft_App_WrCoCmd_Buffer(phost,STENCIL_OP(INCR,INCR));//pass or fail increment	
		Ft_App_WrCoCmd_Buffer(phost,POINT_SIZE(SmallNumCircleRad * 16) );
		Ft_App_WrCoCmd_Buffer(phost,COLOR_A(255));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255 ,255 ,255));	
	        Serial.print("Start time:");
        time = millis();
        Serial.println(time);
		/* Placement of number circles which will move around the rotary */		
		for(theta=StartTheta;theta<=EndTheta ;theta+=IncTheta)			
		{	
			
			th = theta;		
			if(theta == StartTheta + IncTheta) tagval = 9;	
			
			/* limit threshold level near finger stop*/
			/* for value 0 - tag is 10*/
			if((NextTh > EndTheta) && (ReadTag == 10))
			{
				NextTh = EndTheta;
				thresholdflag =1;
			}
			
			/* for value 1 to 9 - threshold*/
			for(i = 1,j=9; i<=9, j>=1;i++,j--)
			{
				if((NextTh > EndTheta - (i*IncTheta)) && (ReadTag == j))
				{
					NextTh = EndTheta - (i*IncTheta);
					thresholdflag =1;
				}
			}
						
			if((BaseTrackValInit + BaseTrackValSign) < BaseTrackValInit)
			{
				NextTh = 0;
			}
			th = th + NextTh;		
			

			//play click sound 

			
			th = da(th);	

			// calculate x and  y for placing circles according to degree
			polarxy(CentreWhiteCircle,th,&VertexX ,&VertexY ,ScreenWidthMid,ScreenHeightMid);	
			Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(1));
		
			Ft_App_WrCoCmd_Buffer(phost,TAG(tagval));
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(200 ,99 ,0)); // for 3d effect adding circles of darker color
			Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(VertexX-24,VertexY-24));
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0 ,0 ,0)); 
			Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(VertexX+24,VertexY+24));// for 3d effect adding circles of darker color
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255 ,255 ,255));	
			Ft_App_WrCoCmd_Buffer(phost,VERTEX2F(VertexX,VertexY));// the base number circle
                       

			
			tagval--;	
			Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(0));			
		}


		        Serial.print("End time:");
        time = millis();
        Serial.println(time);
        			if((NextTh > MaxTheta) && (Touch != NoTouch))
			{
				Ft_Gpu_Hal_Wr8(phost, REG_VOL_SOUND,0xFF);
				Ft_Gpu_Hal_Wr16(phost, REG_SOUND,0x51);
				Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
				MinTheta = MinTheta + IncTheta;
				MaxTheta = MaxTheta + IncTheta;		
			}
			else if((NextTh < MinTheta) && (Touch != NoTouch))
			{
				Ft_Gpu_Hal_Wr8(phost, REG_VOL_SOUND,0xFF);
				Ft_Gpu_Hal_Wr16(phost, REG_SOUND,0x51);
				Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
				MinTheta = MinTheta - IncTheta;
				MaxTheta = MaxTheta - IncTheta;		
			}
		/* Placement of NUmbers inside the white circle - using stencil effect*/
		/*Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(0));*/
		Ft_App_WrCoCmd_Buffer(phost,STENCIL_FUNC(GEQUAL,1,255));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0 ,0 ,0));
		Ft_App_WrCoCmd_Buffer(phost,BEGIN(BITMAPS));
		i=0;
		for(theta=StartTheta;theta<=EndTheta;theta+=IncTheta)		
		{
			
			th = theta;
			th = da(th);	
			temp = 0;//FontSize - 16;	
			if(theta  == StartTheta +30) i = 9;			
                        j = i+'0';
			FontWid = ft_pgm_read_byte(&g_Gpu_Fonts[temp].FontWidth[j]);
                        //FontWid = 12;/* for characters 0 to 9*/
			FontHt = ft_pgm_read_byte(&g_Gpu_Fonts[temp].FontHeightInPixels);
			polarxy(CentreWhiteCircle,th,&VertexX,&VertexY,ScreenWidthMid,ScreenHeightMid);
			FontPLaceX = (VertexX/16) - (FontWid/2);
			FontPLaceY = (VertexY/16) - (FontHt/2);                       
			Ft_Gpu_CoCmd_Number(phost,FontPLaceX,FontPLaceY,28,0,i);			
			i--;
		}

		Ft_App_WrCoCmd_Buffer(phost,STENCIL_OP(KEEP,KEEP));
                Ft_App_WrCoCmd_Buffer(phost,STENCIL_FUNC(ALWAYS,0,255));
                Ft_App_WrCoCmd_Buffer(phost,COLOR_A(128));
		for(theta=StartTheta;theta<=EndTheta;theta+=IncTheta)		
		{
			th = theta;
			th = da(th);	
			temp = 0;//ontSize - 16;	
			if(theta  == StartTheta +30) i = 9;			
			j = i+'0';
			FontWid = ft_pgm_read_byte(&g_Gpu_Fonts[temp].FontWidth[j]);
                        //FontWid = 12;/* for characters 0 to 9*/
			FontHt =  ft_pgm_read_byte(&g_Gpu_Fonts[temp].FontHeightInPixels);
			polarxy(CentreWhiteCircle,th,&VertexX,&VertexY,ScreenWidthMid,ScreenHeightMid);
			FontPLaceX = (VertexX/16) - (FontWid/2);
			FontPLaceY = (VertexY/16) - (FontHt/2);                        
			Ft_Gpu_CoCmd_Number(phost, FontPLaceX,FontPLaceY,28,0,i);			
			i--;

		}
                if((PrevTag == 0)&& ((ReadTag !=0)&&(ReadTag !=255)) && ( Penup = 1))
                {
		      Ft_Gpu_Hal_Wr8(phost, REG_VOL_SOUND,0xFF);
		      Ft_Gpu_Hal_Wr16(phost, REG_SOUND,0x51);
		      Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
                      Penup = 0;
                }
  
		/* dial button (tag 100) - play dtmf sound */
		if((Tagcheck == 100)  && (flag == 1))
		{
			if(k>0)
			{
				//ft_delay(200);
				for(i=0;i<k;i++)
				{
					/* Play the dtmf sound */
					Ft_Gpu_Hal_Wr16(phost, REG_SOUND,StringArray[i]);
					Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
                                        Ft_Gpu_Hal_Sleep(80);
					Ft_Gpu_Hal_Wr16(phost, REG_SOUND,0);
					Ft_Gpu_Hal_Wr8(phost, REG_PLAY,1);
					 Ft_Gpu_Hal_Sleep(80);
				}
			}

		}

		/* reject button (tag -200) clear the string */
		if((Tagcheck == 200) && (flag ==1) )
		{
			for(i =0;i<=k;i++)
			{
				StringArray[i] = '\0';
			}
			k=0;

		}

		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255,255,255));
		Ft_App_WrCoCmd_Buffer(phost,COLOR_A(255));
		Ft_App_WrCoCmd_Buffer(phost,BEGIN(BITMAPS));		

		/* dial image*/
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255,255,255));
		Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(1));
		Ft_App_WrCoCmd_Buffer(phost,TAG(100));
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2II(ScreenWidthMid-131,FT_DispHeight-70,2,0));
		Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(0));		
		
		/* display numbers in the centre of the point while dialing*/
		if((PrintTag >0 ) && (PrintTag <= 10) && (Touch != NoTouch))
		{
		//	printf("%d,",ReadTag);
			if (PrintTag == 10)PrintTag = 0;
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0,0,0));
			Ft_Gpu_CoCmd_Number(phost,(ScreenWidthMid - 16)/*225*/,(ScreenHeightMid - 27)/*110*/,31,0,PrintTag);
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0,0,0));
			Ft_Gpu_CoCmd_Number(phost,(ScreenWidthMid - 14)/*225*/,(ScreenHeightMid - 25)/*110*/,31,0,PrintTag);
			Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255,255,255));
			Ft_Gpu_CoCmd_Number(phost,(ScreenWidthMid - 15)/*225*/,(ScreenHeightMid - 26)/*110*/,31,0,PrintTag);
			if (PrintTag == 0)PrintTag = 10;
		}
		/* fingerstop jpg */		
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255,255,255));
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2II(FingerstopX/*296*/,FingerstopY/*153*/,0,0)); //exact location of picture		

		/*reject button jpg*/
		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(255,255,255));
		Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(1));
		Ft_App_WrCoCmd_Buffer(phost,TAG(200));
		Ft_App_WrCoCmd_Buffer(phost,VERTEX2II(ScreenWidthMid+80,FT_DispHeight-70,1,0));
		Ft_App_WrCoCmd_Buffer(phost,TAG_MASK(0));


		Ft_Gpu_CoCmd_FgColor(phost, 0xCC9710); // color of number display button
		Ft_Gpu_CoCmd_Button(phost, NoX, NoY -2/*5*/, ButWid, ButHt, 28, 0, "");// placement of button

		Ft_App_WrCoCmd_Buffer(phost,COLOR_RGB(0,0,0));//color of number(text) color
	
		Ft_Gpu_CoCmd_Text(phost,(NoX + ButWid/2),(NoY + ButHt/2),28,OPT_CENTER,StringArray);
		Ft_App_WrCoCmd_Buffer(phost, END());

		Ft_App_WrCoCmd_Buffer(phost,DISPLAY());


                //delay(1000);
		Ft_Gpu_CoCmd_Swap(phost);

		/* Download the commands into fifo */
		Ft_App_Flush_Co_Buffer(phost);

		/* Wait till coprocessor completes the operation */
		Ft_Gpu_Hal_WaitCmdfifo_empty(phost);
		PrevTag = ReadTag;
		PrevTouch = Touch;
		//tmprate++;
		}while(1);
			

}

ft_void_t SAMAPP_BootupConfig()
{
	ft_uint8_t Pclk;
	/* Do a power cycle for safer side */
	Ft_Gpu_Hal_Powercycle(phost,FT_TRUE);

	/* Set the clk to external clock */
	Ft_Gpu_HostCommand(phost,FT_GPU_EXTERNAL_OSC);  
	Ft_Gpu_Hal_Sleep(10);
	  

	/* Switch PLL output to 48MHz */
	Ft_Gpu_HostCommand(phost,FT_GPU_PLL_48M);  
	Ft_Gpu_Hal_Sleep(10);

	/* Do a core reset for safer side */
	Ft_Gpu_HostCommand(phost,FT_GPU_CORE_RESET);     

	/* Access address 0 to wake up the FT800 */
	Ft_Gpu_HostCommand(phost,FT_GPU_ACTIVE_M);  

    Ft_Gpu_Hal_Wr8(phost, REG_GPIO_DIR,0xff | Ft_Gpu_Hal_Rd8(phost,REG_GPIO_DIR));
    Ft_Gpu_Hal_Wr8(phost, REG_GPIO,0x080 | Ft_Gpu_Hal_Rd8(phost,REG_GPIO));
	
	{
		ft_uint8_t chipid;
		//Read Register ID to check if FT800 is ready. 
		chipid = Ft_Gpu_Hal_Rd8(phost, REG_ID);
		while(chipid != 0x7C)
			chipid = Ft_Gpu_Hal_Rd8(phost, REG_ID);
#ifdef MSVC_PLATFORM
		printf("VC1 register ID after wake up %x\n",chipid);
#endif
	}
	Pclk = FT_DispPCLK;

        Ft_Gpu_Hal_Wr8(phost,REG_GPIO_DIR,0xFF);
	Ft_Gpu_Hal_Wr8(phost,REG_GPIO,0xFF);//look into data sheet for the various configurations of GPIOs
	Ft_Gpu_Hal_Wr8(phost,REG_VOL_SOUND,255);

	/* Boot up sequence */
	/* Clock is configured in the above code - optional if external clock is not avilable */
	/* By default the display settings are for WQVGA, so first download the first DL into DL memory */
	/* Write FRAME_SWAP into DL_SWAP register */
	/* Followed by enabling PCLK - note that PCLK for WQVGA is 5 and QVGA is 8 - follow DS/PG/AN for more information */
	Ft_Gpu_Hal_WrMem(phost,RAM_DL,(ft_uint8_t *)FT_DLCODE_BOOTUP,12);
	Ft_Gpu_Hal_Wr8(phost,REG_DLSWAP,DLSWAP_FRAME);
	Ft_Gpu_Hal_Wr8(phost,REG_PCLK,Pclk);


Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_A,0x00007ce6);
  Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_B,0xfffffd67);
  Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_C,0xfff55522);
  Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_D,0xfffffe6f);
  Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_E,0xffffb4be);
  Ft_Gpu_Hal_Wr32(phost,REG_TOUCH_TRANSFORM_F,0x0124bca7);
  

	/* Configuration of LCD display */
#ifdef SAMAPP_DISPLAY_QVGA	
	/* Values specific to QVGA LCD display */
	 FT_DispWidth = 320;
	 FT_DispHeight = 240;
	 FT_DispHCycle =  408;
	 FT_DispHOffset = 70;
	 FT_DispHSync0 = 0;
	 FT_DispHSync1 = 10;
	 FT_DispVCycle = 263;
	 FT_DispVOffset = 13;
	 FT_DispVSync0 = 0;
	 FT_DispVSync1 = 2;
	 FT_DispPCLK = 8;
	 FT_DispSwizzle = 2;
	 FT_DispPCLKPol = 0;
#endif

    Ft_Gpu_Hal_Wr16(phost, REG_HCYCLE, FT_DispHCycle);
    Ft_Gpu_Hal_Wr16(phost, REG_HOFFSET, FT_DispHOffset);
    Ft_Gpu_Hal_Wr16(phost, REG_HSYNC0, FT_DispHSync0);
    Ft_Gpu_Hal_Wr16(phost, REG_HSYNC1, FT_DispHSync1);
    Ft_Gpu_Hal_Wr16(phost, REG_VCYCLE, FT_DispVCycle);
    Ft_Gpu_Hal_Wr16(phost, REG_VOFFSET, FT_DispVOffset);
    Ft_Gpu_Hal_Wr16(phost, REG_VSYNC0, FT_DispVSync0);
    Ft_Gpu_Hal_Wr16(phost, REG_VSYNC1, FT_DispVSync1);
    Ft_Gpu_Hal_Wr8(phost, REG_SWIZZLE, FT_DispSwizzle);
    Ft_Gpu_Hal_Wr8(phost, REG_PCLK_POL, FT_DispPCLKPol);
    Ft_Gpu_Hal_Wr8(phost, REG_PCLK,FT_DispPCLK);//after this display is visible on the LCD
    Ft_Gpu_Hal_Wr16(phost, REG_HSIZE, FT_DispWidth);
    Ft_Gpu_Hal_Wr16(phost, REG_VSIZE, FT_DispHeight);


    /* Touch configuration - configure the resistance value to 1200 - this value is specific to customer requirement and derived by experiment */
    Ft_Gpu_Hal_Wr16(phost, REG_TOUCH_RZTHRESH,1200);


}

/* Boot up for FT800 followed by graphics primitive sample cases */
/* Initial boot up DL - make the back ground green color */
//const ft_uint8_t FT_DLCODE_BOOTUP[12] = 
//{
//    0,255,0,2,//GPU instruction CLEAR_COLOR_RGB
//    7,0,0,38, //GPU instruction CLEAR
//    0,0,0,0,  //GPU instruction DISPLAY
//};
#ifdef MSVC_PLATFORM
/* Main entry point */
ft_int32_t main(ft_int32_t argc,ft_char8_t *argv[])
#endif
#ifdef ARDUINO_PLATFORM
ft_void_t setup()
#endif
{
	Ft_Gpu_HalInit_t halinit;
        Serial.begin(9600);
	halinit.TotalChannelNum = 1;

              
	Ft_Gpu_Hal_Init(&halinit);
	host.hal_config.channel_no = 0;
#ifdef MSVC_PLATFORM_SPI
	host.hal_config.spi_clockrate_khz = 12000; //in KHz
#endif
#ifdef ARDUINO_PLATFORM_SPI
	host.hal_config.spi_clockrate_khz = 2000; //in KHz
#endif
        Ft_Gpu_Hal_Open(&host);
            
	phost = &host;
    Serial.println("before config");
    SAMAPP_BootupConfig();

    /*It is optional to clear the screen here*/	
    Ft_Gpu_Hal_WrMem(phost, RAM_DL,(ft_uint8_t *)FT_DLCODE_BOOTUP,sizeof(FT_DLCODE_BOOTUP));
    Ft_Gpu_Hal_Wr8(phost, REG_DLSWAP,DLSWAP_FRAME);
    
    Ft_Gpu_Hal_Sleep(1000);//Show the booting up screen. 
    
#ifdef SAMAPP_ENABLE_ROTARY_DEMO
    Serial.print("before calibration");
	SAMAPP_CoPro_Widget_Calibrate();

	Rotary_Dial_phone();
#endif


	/* Close all the opened handles */
    Ft_Gpu_Hal_Close(phost);
    Ft_Gpu_Hal_DeInit();
#ifdef MSVC_PLATFORM
	return 0;
#endif
}

void loop()
{
}



/* Nothing beyond this */




