/*******************************************************************
*  include files
*******************************************************************/
#if defined(__ADSPBF537__)		/* __ADSPBF537__ */
#include <cdefBF537.h>
#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */
#include <cdefBF526.h>
#elif defined(__ADSPBF518__)	/* __ADSPBF526__ */
#include <cdefBF518.h>
#else
#error *** Processor not supported ***		/* NOT DEFINED */
#endif

#include <stdio.h>
#include <sys\exception.h>
#include <ccblkfn.h>
#include <sysreg.h>
#include <signal.h>
#include "ad7147.h"
//#include "..\lcd_buffers.h"
//#include "..\LCD\lq035q1dh02.h"
//#include "..\TouchScreen\ad7879.h"
#include "lcd_buffers.h"
#include "lq035q1dh02.h"
#include "ad7879.h"

/*******************************************************************
*  defines
*******************************************************************/

/* Touchwheel specific definitions */
#define NUMBER_OF_STAGES_BEING_USED					0x00FF	/* 1 sensor=0x0001; 2 sensor=0x0003; 3 sensor=0x0007, etc, etc */
#define LOWER_SENSOR_STAGE							0x0001
#define HIGHER_SENSOR_STAGE							0x0080

#define NB_OF_SENSORS_FOR_TW						8
#define NUMBER_OF_SENSORS_ON_FOR_BIG_FINGER			4
#define SENSOR_RESOLUTION							64
#define WEIGHT_FACTOR								30		/* The weights will determine the number of positions. */
#define NUMBER_OF_WANTED_POSITIONS					127
#define NUMBER_OF_INTS_BEFORE_THRESH_INT_MODE		8

/* Definitions for the tap */
#define T_MIN_TOUCHING								1
#define T_MAX_TOUCHING								8
#define T_MIN_NO_TOUCHING							5
#define DISPLAY_AFTER_A_TAP							3
#define T_NO_TOUCHING_MULTI_TAP						5
#define TIME_BEFORE_REINITIALISATION				10

/* Other definitions */
#define FIFOLENGTH									4
#define SMALL_FIFOLENGTH							2
#define NB_OF_INT									3
#define NUMBER_OF_SENSOR_VALUES_TO_SET_LIFT_OFF		20
#define NUMBER_OF_POSITIONS_TO_ACTIVATE				8

#define bit bool

/* Will determine how many lines display in 1 full turn */
#define DISPLAY_ITEMS_CONSTANT						60

/*******************************************************************
*  function prototypes
*******************************************************************/
static void Process_Scroll_Wheel_Touch(void);
static void Process_PB_Touch(void);
static void Service_AD7147_Isr(void);
static void Move_Data_In_Fifo(unsigned short *FifoName, int *SignedFifo, const unsigned char FifoLength, const unsigned short newData, const bit FifoType);
static void Initialize_Fifo(unsigned short *FifoName, const unsigned char FifoLength, const unsigned short InitValue);
static void Initialize_Touch_Wheel(unsigned short *AmbientVals, unsigned short *MaxAvgVals);
static unsigned char Find_Highest_And_Lowest_Stages_Used(const unsigned short InterruptStatusRegister, const unsigned short LowestStageOfTheSensor, const unsigned short HighestStageOfTheSensor, const unsigned char NumberOfStagesUsed, const unsigned char BigFingerLevel, unsigned char *LowestSensorTouched, unsigned char *HighestSensorTouched);

static void Set_LCD_Color(u16 Color, u16 LineNumber);
static void Fill_Line(u16 LineNumber, bool bGoingDown);

/*******************************************************************
*  global variables
*******************************************************************/

/* Variable which returns the status of Scrollwheel. */
unsigned short  ScrollWheelStatus;

/* Variables for initialisation, protocol and re-calibration */
unsigned char  InterruptCounterForTouchwheelInitialisation;

/* Variables for the touchwheel */
unsigned short  CurrentValues[NB_OF_SENSORS_FOR_TW];
unsigned short  AmbientValues[NB_OF_SENSORS_FOR_TW];
unsigned short  MaxAverages[NB_OF_SENSORS_FOR_TW];

/* Variables for the scaled down ADC values */
unsigned short  Resolutions[NB_OF_SENSORS_FOR_TW];
unsigned short  SensorValues[NB_OF_SENSORS_FOR_TW];
unsigned short  SensorValuesFifo[NB_OF_SENSORS_FOR_TW * SMALL_FIFOLENGTH];
unsigned short  MaxSensorValues[NB_OF_SENSORS_FOR_TW];

/* Variables to find the lowest and the highest sensor touched */
unsigned char  LowestSensorBeingTouched,  HighestSensorBeingTouched;

/* Variable to track Touching Error */
unsigned char  PreviousTouchError;

/* Variables to find out which sensor has the highest value. */
unsigned char  SensorWithHighestValue,  PreviousSensorWithHighestValue;

/* Variables for the lift off */
unsigned char  SensorBeforeTheHighest,  SensorAfterTheHighest;
unsigned char  SecondSensorBeforeTheHighest,  SecondSensorAfterTheHighest;
unsigned char  EnableMaxSensorValue[NB_OF_SENSORS_FOR_TW];
bit LiftOffDetected;

/* Variables for absolute positions */
int  MeanValue,  PreviousMeanValue,  MeanValueWithoutOffset;
unsigned char  PositionOnTw,  PositionOffset;
unsigned short  PositionFifo[SMALL_FIFOLENGTH];
unsigned short  MeanValueFifo[SMALL_FIFOLENGTH];
float  PositionRatio;

/* Variables for activation */
unsigned char  FirstTimeTouchWheelTouched;
unsigned char  ScrollWheelTouchDownCounter;
bit TouchwheelProperlyTouched;
bit TouchwheelFlag;
/* Variables for the tap */

unsigned char  ReturnTappingCounterOnTw;
unsigned char  NoTouchCounterOnTw;
bit EnableTapDisplayOnTw;
bit TappingFlag;

/* Variables for multiple taps */
unsigned char  MultiTapNoTouchCounterOnTw;
unsigned char  FirstTouchInitCounter;
unsigned char  MultiTapDetected;
bit ResetMultiTapNoTouchCounterOnceOnTw;

/* Variables to find the peak during activation */
bit AllowDisplayAfterActivation, MovementDetectedOnActivation;

unsigned char  NbOfSensorsWithFastRateOfChange,  PreviousNbOfSensorsWithFastRateOfChange;
unsigned char  FastRateOfChangeDetected;

/* Variables used for scrolling */
int  TwelveOclockDisplacement;
int  RelativeDisplacement;
unsigned short  DisplayItemsResolution;
unsigned char  PositionOnFirstTouch;
unsigned char  TwelveOclockPosition;
unsigned char  TwelveOclockPointFound;
bit UpdateDownOnce, UpdateUpOnce;

/* Variables to set a flag after scrolling 32 positions since activation */
unsigned char  PositionOnFirstTouchForActivation;
unsigned char  TwelveOclockPoint;
unsigned char  DispRelatedToFirstTouch;
unsigned char  TwelveOclockDispRelatedToFirstTouch;
bit DisplacementDetectedSinceActivation;
unsigned char  NumberOfPositionsAllowed;

/* Variable for switching from 1 int mode to another one */
unsigned char  InterruptCounterForThresIntMode;


unsigned short AD7147Registers[24];	/* [0...23 inc]=1st set of registers [0...23 inc]
								 	   Element[23] = 0x17 = ID register @ 0x17 */

u16 ButtonPressed = 0;		/* keeps track of the PBs pressed */
u16 CurrentLineNumber = 0;	/* current line for scroll wheel */
u16 LCDColor = 0;			/* current lCD backround color */

extern u16 Frame0[];

/* This is part of the front porch and will not
   be displayed */
extern u16 TempFrame[];

/* Dummy buffer to account for the front porch */
extern DESCRIPTOR_LARGE DummyBuffer[2];
extern DESCRIPTOR_LARGE Buffer1[LCD_NUM_FRAMES_DISPLAY];


/****************************************************************************
*   Function:    Fill_Line
*   Description: fills the line designated by LineNumber with white if
*				 scrolling down or the backround color if scrolling up
******************************************************************************/
void Fill_Line(u16 LineNumber, bool bGoingDown)
{
	u32     Line,Pixel,ColorId;
	volatile int i = 0;
	u16 Color = RGB565_WHITE;

	if( bGoingDown )
	{
		/* make the line white if scrolling down */
		Color = RGB565_WHITE;
	}
	else
	{
		/* make the line the same color as the backround if scrolling up */
		Color = LCDColor;
	}

	/* figure out where in the buffer we need to change based on the line number */
	i = LineNumber * 320;

    /* change the color of the line */
	for (Pixel = 1; Pixel <= LCD_PIXELS_PER_LINE; Pixel++ )
	{
		Frame0[i++] = Color;
	}

}

/****************************************************************************
*   Function:    Set_LCD_Color
*   Description: changes the color of the LCD backround
******************************************************************************/
void Set_LCD_Color(u16 Color, u16 LineNumber)
{
	u32     Line,Pixel;
	volatile int i = 0;

	/* figure out the location in our buffer to start based
	   on the line number */
	i = LineNumber * 320;

    /* change the LCD backround color */
	for (; i < LCD_PIXELS_PER_LINE * LCD_LINES_PER_FRAME; )
	{
		Frame0[i++] = Color;
	}

}

/*******************************************************************
*   Function:    CAP_TOUCHIRQ_ISR
*   Description: ISR for INT
*******************************************************************/
EX_INTERRUPT_HANDLER(CAP_TOUCHIRQ_ISR)
{
	/* disable interrupts */
	Disable_INT();

	/* service the interrupt */
	Service_AD7147_Isr();

	/* enable interrupts */
	Enable_INT();
}

/****************************************************************************
*   Function:    Process_PB_Touch
*   Description: PB was touched so process it
******************************************************************************/
static void Process_PB_Touch(void)
{
	static u16 CurrentButtonPressed = 0;

	/* Recover from errors if needed */
	if (((AD7147Registers[STAGE_LOW_LIMIT_INT] & POWER_UP_INTERRUPT) != 0x0000) &&
		((AD7147Registers[STAGE_HIGH_LIMIT_INT] & POWER_UP_INTERRUPT) == 0x0000))
	{
		Do_Calibration();
	}
	else
		/* get the button that was pressed */
		CurrentButtonPressed = ((AD7147Registers[STAGE_HIGH_LIMIT_INT] & 0xFFF) >> 8);


	/* if a button was pressed clear our current LCD color */
	if( CurrentButtonPressed )
		LCDColor = 0;

	/* change the color of the LCD depending on which button was pressed */
	if( (CurrentButtonPressed & 0x1) == 0x1 )
		LCDColor |= RGB565_RED;

	if( (CurrentButtonPressed & 0x2) == 0x2 )
		LCDColor |= RGB565_GREEN;

	if( (CurrentButtonPressed & 0x4) == 0x4 )
		LCDColor |= RGB565_BLUE;

	if( (CurrentButtonPressed & 0x8) == 0x8 )
		LCDColor |= RGB565_YELLOW;

	/* ButtonPressed will keep track of which buttons have been pressed.
	   When all have been pressed the test is complete */
	ButtonPressed |= CurrentButtonPressed;

	/* change the color of the LCD */
	Set_LCD_Color(LCDColor, CurrentLineNumber);
}

/****************************************************************************
*   Function:    Process_Scroll_Wheel_Touch
*   Description: Scrollwheel was touched so process it
******************************************************************************/
static void Process_Scroll_Wheel_Touch(void)
{
	unsigned short MaxAvgAddress;
	unsigned short AmbientValueAddress;
	unsigned short WeightedSensorValues[NB_OF_SENSORS_FOR_TW];
	unsigned short MeanValueNum,  MeanValueDen;
	unsigned char TouchError = 0;
	int tempResult;
	unsigned char i;

	/*****************************************************************
	* Get the Current, Ambient and Max Average Values from the chip *
	*****************************************************************/
	Read_AD7147(ADCRESULT_S0, CurrentValues, NB_OF_SENSORS_FOR_TW);

	AmbientValueAddress=STAGE0_AMBIENT;
	MaxAvgAddress=STAGE0_MAX_AVG;
	for(i=0;i<NB_OF_SENSORS_FOR_TW;i++)
	{
		Read_AD7147(AmbientValueAddress, &AmbientValues[i], 1);
		Read_AD7147(MaxAvgAddress, &MaxAverages[i], 1);

		AmbientValueAddress=AmbientValueAddress+NB_OF_REGS_PER_STAGE;
		MaxAvgAddress=MaxAvgAddress+NB_OF_REGS_PER_STAGE;
	}

	if(InterruptCounterForTouchwheelInitialisation<(NB_OF_INT+2))
	{
		if (InterruptCounterForTouchwheelInitialisation==(NB_OF_INT-1))
		{
			/****************************************
			* Put initialization code here
			****************************************/
			Initialize_Touch_Wheel(AmbientValues, MaxAverages);
		}
		InterruptCounterForTouchwheelInitialisation++;
	}

	if(InterruptCounterForTouchwheelInitialisation>=NB_OF_INT)
	{

		/* Recover from errors if needed */
		if (((AD7147Registers[STAGE_LOW_LIMIT_INT] & POWER_UP_INTERRUPT) != 0x0000) &&
			((AD7147Registers[STAGE_HIGH_LIMIT_INT] & POWER_UP_INTERRUPT) == 0x0000))
		{
			Do_Calibration();

			/* Initialize again after we have recovered from error */
			Initialize_Touch_Wheel(AmbientValues, MaxAverages);
		}

		/*************************
		* Change interrupt mode *
		*************************/
		if (((AD7147Registers[STAGE_HIGH_LIMIT_INT] & POWER_UP_INTERRUPT)!=0x0000) || ((AD7147Registers[STAGE_LOW_LIMIT_INT] & POWER_UP_INTERRUPT)!=0x0000))
		{
			/* Configure the AD7147 in End Of Conversion interrupt mode */
			if (AD7147Registers[STAGE_COMPLETE_INT_EN]==0x0000)
			{
				AD7147Registers[STAGE_LOW_INT_EN] &= 0xF000;
				AD7147Registers[STAGE_HIGH_INT_EN] &= 0xF000;
				AD7147Registers[STAGE_COMPLETE_INT_EN]=0x0001;
				Write_AD7147(STAGE_LOW_INT_EN, &AD7147Registers[STAGE_LOW_INT_EN], 3);
			}
			InterruptCounterForThresIntMode=NUMBER_OF_INTS_BEFORE_THRESH_INT_MODE;
		}
		else
		{
			/* Configure  the AD7147 in button interrupt driven mode */
			if (InterruptCounterForThresIntMode>0)
				InterruptCounterForThresIntMode--;
			if (AD7147Registers[STAGE_HIGH_INT_EN]==0x0000 && InterruptCounterForThresIntMode==0)
			{
				AD7147Registers[STAGE_LOW_INT_EN] |= POWER_UP_INTERRUPT;
				AD7147Registers[STAGE_HIGH_INT_EN] |= 0x0FFF;
				AD7147Registers[STAGE_COMPLETE_INT_EN]=0x0000;
				Write_AD7147(STAGE_LOW_INT_EN, &AD7147Registers[STAGE_LOW_INT_EN], 3);
			}
		}

		/*********************************************************************************************
		**********************************************************************************************
		**																							**
		**************************************** SCROLLWHEEL *****************************************
		**																							**
		*********************************************************************************************/

		/*******************************************
		* Find which stages have an interrupt set *
		*******************************************/
		PreviousTouchError=TouchError;
		TouchError=Find_Highest_And_Lowest_Stages_Used(AD7147Registers[STAGE_HIGH_LIMIT_INT], LOWER_SENSOR_STAGE, HIGHER_SENSOR_STAGE,
									  			 NB_OF_SENSORS_FOR_TW, NUMBER_OF_SENSORS_ON_FOR_BIG_FINGER,
												 &LowestSensorBeingTouched, &HighestSensorBeingTouched);

		/*************************
		* Touchwheel activation
		*************************/
		if(((AD7147Registers[STAGE_HIGH_LIMIT_INT] & NUMBER_OF_STAGES_BEING_USED) != 0x0000))
		{
			TouchwheelFlag=1;
			TappingFlag=0;		/* Touching therefore clear the tapping flag. */
			ScrollWheelStatus &= 0xBFFF;

			/* Touchwheel touched for the first time */
			if (FirstTimeTouchWheelTouched==0)
				FirstTimeTouchWheelTouched=1;

			/* Allow the counter for the multiple taps to start again after a touch */
			ResetMultiTapNoTouchCounterOnceOnTw=1;

			for(i=0;i<NB_OF_SENSORS_FOR_TW;i++)
    	    {
			   	/* Calculate the resolution */
   	        	Resolutions[i]=(MaxAverages[i]-AmbientValues[i])/SENSOR_RESOLUTION;

			    /* Calculate the scaled down sensor values and keep track of them */
				SensorValues[i]=abs(CurrentValues[i]-AmbientValues[i])/Resolutions[i];

				if(FirstTimeTouchWheelTouched==1)
				{
					SensorValuesFifo[i]=SensorValues[i];
					SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW]=SensorValues[i];
				}
				else if(FirstTimeTouchWheelTouched==2)
				{
					SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW]=SensorValuesFifo[i];
					SensorValuesFifo[i]=SensorValues[i];
				}
			}/* End for(...) */

			/* Check if the user left enough time between 2 taps. */
			if (NoTouchCounterOnTw > T_MIN_NO_TOUCHING)
				ReturnTappingCounterOnTw=DISPLAY_AFTER_A_TAP; /* Reset counter for displaying the tap */
			else
				ReturnTappingCounterOnTw=0;

			if (ScrollWheelTouchDownCounter<26)
			{
				if (ScrollWheelTouchDownCounter>=13)    /* 13 interrupts */
				{
					TouchwheelProperlyTouched=1;		/* Set a flag once we are touching for longer than 13 interrupts */
					MovementDetectedOnActivation=1;
					AllowDisplayAfterActivation=1;
				}
				/* Touching for more than 13 interrupts, hence clear the NoTouchCounter */
				if (ScrollWheelTouchDownCounter > (T_MIN_TOUCHING+T_MAX_TOUCHING))
					NoTouchCounterOnTw=0;

				ScrollWheelTouchDownCounter++;
			}
			else
			{
				NoTouchCounterOnTw=0;
				ScrollWheelTouchDownCounter=255;
			}
		}
		else if((AD7147Registers[STAGE_HIGH_LIMIT_INT] & NUMBER_OF_STAGES_BEING_USED) == 0x0000)
		{
			TouchwheelFlag=0;
			FirstTimeTouchWheelTouched=0;
			TouchwheelProperlyTouched=0;
			MovementDetectedOnActivation=0;
			ScrollWheelStatus &= 0x7FFF;
			TwelveOclockPosition=NUMBER_OF_WANTED_POSITIONS;
			AllowDisplayAfterActivation=0;

			/* Variables to calculate 20 positions after activation */
			DisplacementDetectedSinceActivation=0;
			TwelveOclockDispRelatedToFirstTouch=0;
			DispRelatedToFirstTouch=0;
			TwelveOclockPoint=0;


			/* Work out the time between multiple taps */
			/*******************************************/
			/* Reset the counter as soon as we lift off */
			if(ResetMultiTapNoTouchCounterOnceOnTw==1)
			{
				ResetMultiTapNoTouchCounterOnceOnTw=0;
				MultiTapNoTouchCounterOnTw=0;
			}
			/* Start counting away */
			if (MultiTapNoTouchCounterOnTw<50)
			{
				FirstTouchInitCounter=0;
				if(MultiTapNoTouchCounterOnTw>=T_NO_TOUCHING_MULTI_TAP)
				{
					MultiTapDetected=0;
					FirstTouchInitCounter=255;
				}
				MultiTapNoTouchCounterOnTw++;
			}

			/* Work out the tap */
			if (NoTouchCounterOnTw<26)
				NoTouchCounterOnTw++;

			if (ScrollWheelTouchDownCounter>T_MIN_TOUCHING && ScrollWheelTouchDownCounter<T_MAX_TOUCHING &&
				NoTouchCounterOnTw > ScrollWheelTouchDownCounter)
			{
				/* Set a bit for a certain number of interrupts so that the user application sees it.
				   This is done with a decounter that is reloaded when we are touching */
				if (ReturnTappingCounterOnTw>0 && EnableTapDisplayOnTw==1)
				{
					ReturnTappingCounterOnTw--;
					TappingFlag=1;	/* Tap detected here */
				}
				else
				{
					ScrollWheelTouchDownCounter=0;
					TappingFlag=0;
				}
			}
			else
			{
				ScrollWheelTouchDownCounter=0;
				ReturnTappingCounterOnTw=0;
				TappingFlag=0; /* Cleared tapping bit after lift off */
			}
		}


		/***************************************************
		* Check for the rate of change on all the sensors *
		***************************************************
		* If the rate of change of the sensor values is big then we know that we're tapping. */
		PreviousNbOfSensorsWithFastRateOfChange=NbOfSensorsWithFastRateOfChange;
		NbOfSensorsWithFastRateOfChange=0;
		for (i=0;i<NB_OF_SENSORS_FOR_TW;i++)
		{
			FastRateOfChangeDetected=0;
			if (SensorValuesFifo[i] > (SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW]+15))
				FastRateOfChangeDetected=1;
			else
				FastRateOfChangeDetected=0;
			NbOfSensorsWithFastRateOfChange = NbOfSensorsWithFastRateOfChange | (FastRateOfChangeDetected<<i);
		}
		/* Set a flag after a fast rate of change. */
		if (NbOfSensorsWithFastRateOfChange==0 && PreviousNbOfSensorsWithFastRateOfChange!=0)
			AllowDisplayAfterActivation=1;

		if (NbOfSensorsWithFastRateOfChange!=0 && PreviousNbOfSensorsWithFastRateOfChange!=0 &&
			NbOfSensorsWithFastRateOfChange!=PreviousNbOfSensorsWithFastRateOfChange)
		{
			AllowDisplayAfterActivation=1;
			MovementDetectedOnActivation=1;
		}


		if (TouchwheelFlag==1)
		{
			/*********************************************************************
			* Peak detector that finds the sensor that has the highest response *
			*********************************************************************/
			PreviousSensorWithHighestValue=SensorWithHighestValue;

			SensorWithHighestValue=0;
			for (i=0;i<NB_OF_SENSORS_FOR_TW;i++)
			{
				if (i<(NB_OF_SENSORS_FOR_TW-1))
				{
					if((SensorValues[i]>SensorValues[i+1]) && (SensorValues[i]>SensorValues[SensorWithHighestValue]))
						SensorWithHighestValue=i;
				}
				else if (i==(NB_OF_SENSORS_FOR_TW-1))
				{
					if((SensorValues[i]>SensorValues[0]) && (SensorValues[i]>SensorValues[SensorWithHighestValue]))
						SensorWithHighestValue=i;
				}
			}

			/* Identify sensors on each side of the one with the highest response */
			if(SensorWithHighestValue==0)
			{
				SecondSensorBeforeTheHighest=6;
				SensorBeforeTheHighest=7;
				SensorAfterTheHighest=1;
				SecondSensorAfterTheHighest=2;
			}
			else if(SensorWithHighestValue==1)
			{
				SecondSensorBeforeTheHighest=7;
				SensorBeforeTheHighest=0;
				SensorAfterTheHighest=2;
				SecondSensorAfterTheHighest=3;
			}
			else if (SensorWithHighestValue==6)
			{
				SecondSensorBeforeTheHighest=4;
				SensorBeforeTheHighest=5;
				SensorAfterTheHighest=7;
				SecondSensorAfterTheHighest=0;
			}
			else if (SensorWithHighestValue==7)
			{
				SecondSensorBeforeTheHighest=5;
				SensorBeforeTheHighest=6;
				SensorAfterTheHighest=0;
				SecondSensorAfterTheHighest=1;
			}
			else if (SensorWithHighestValue !=255)
			{
				SecondSensorBeforeTheHighest=SensorWithHighestValue-2;
				SensorBeforeTheHighest=SensorWithHighestValue-1;
				SensorAfterTheHighest=SensorWithHighestValue+1;
				SecondSensorAfterTheHighest=SensorWithHighestValue+2;
			}
		}/* End if (TouchwheelFlag==1) */

		/* Calculate Peak SensorValue that will be useful to determine the lift off */
		for (i=0; i<NB_OF_SENSORS_FOR_TW; i++)
		{
			if (i==SensorWithHighestValue)
			{
				if (EnableMaxSensorValue[i]==1)
				{
					EnableMaxSensorValue[i]=0;
					if (SensorValuesFifo[i] > SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW])
						MaxSensorValues[i]=MaxSensorValues[i] * 0.5 + SensorValuesFifo[i] * 0.5;
					else
						MaxSensorValues[i]=MaxSensorValues[i] * 0.5 + SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW] * 0.5;
				}
				/* Quick update */
				if (SensorValues[i]>MaxSensorValues[i])
					MaxSensorValues[i]=SensorValuesFifo[i];
			}
			else
				EnableMaxSensorValue[i]=1;
		}

		/*************************
		* Work out the lift off
		*************************/
		/* Prevents slight position movements when lifting off */
		LiftOffDetected=0;
		if (TouchwheelFlag==1)
		{
			/* If the amplitude of the highest sensor decreases, then set a flag. */
			if (abs(MaxSensorValues[SensorWithHighestValue] - SensorValues[SensorWithHighestValue])>NUMBER_OF_SENSOR_VALUES_TO_SET_LIFT_OFF)
				LiftOffDetected=1;
			else
				LiftOffDetected=0;
		}
		else
			LiftOffDetected=1;


		/*********************************************************************************************
		*																							 *
		******************* CODE FOR THE ABSOLUTE DISPLACEMENT ON THE SCROLLWHEEL *******************
		*																							 *
		*********************************************************************************************/
		if((TouchError & 0x01)!=0x01)
		{
			/*********************************
			* Calculation of the mean value
			*********************************/
			/* Modify the weights around 12.00 o'clock */
			switch (SensorWithHighestValue)
			{
				case 0:	/* Sensor 0 has the highest reponse */
					WeightedSensorValues[0]=SensorValues[SecondSensorBeforeTheHighest] * WEIGHT_FACTOR;
					WeightedSensorValues[1]=SensorValues[SensorBeforeTheHighest] * WEIGHT_FACTOR * 2;
					WeightedSensorValues[2]=SensorValues[SensorWithHighestValue] * WEIGHT_FACTOR * 3;
					WeightedSensorValues[3]=SensorValues[SensorAfterTheHighest] * WEIGHT_FACTOR * 4;
					WeightedSensorValues[4]=SensorValues[SecondSensorAfterTheHighest] * WEIGHT_FACTOR * 5;
					break;
				case 1:	/* Sensor 1 has the highest reponse */
					WeightedSensorValues[0]=SensorValues[SecondSensorBeforeTheHighest] * WEIGHT_FACTOR * 2;
					WeightedSensorValues[1]=SensorValues[SensorBeforeTheHighest] * WEIGHT_FACTOR * 3;
					WeightedSensorValues[2]=SensorValues[SensorWithHighestValue] * WEIGHT_FACTOR * 4;
					WeightedSensorValues[3]=SensorValues[SensorAfterTheHighest] * WEIGHT_FACTOR * 5;
					WeightedSensorValues[4]=SensorValues[SecondSensorAfterTheHighest] * WEIGHT_FACTOR * 6;
					break;
				case 6:	/* Sensor 6 has the highest reponse */
					WeightedSensorValues[0]=SensorValues[SecondSensorBeforeTheHighest] * WEIGHT_FACTOR * 7;
					WeightedSensorValues[1]=SensorValues[SensorBeforeTheHighest] * WEIGHT_FACTOR * 8;
					WeightedSensorValues[2]=SensorValues[SensorWithHighestValue] * WEIGHT_FACTOR * 9;
					WeightedSensorValues[3]=SensorValues[SensorAfterTheHighest] * WEIGHT_FACTOR * 10;
					WeightedSensorValues[4]=SensorValues[SecondSensorAfterTheHighest] * WEIGHT_FACTOR * 11;
					break;
				case 7:	/* Sensor 7 has the highest reponse */
					WeightedSensorValues[0]=SensorValues[SecondSensorBeforeTheHighest] * WEIGHT_FACTOR * 8;
					WeightedSensorValues[1]=SensorValues[SensorBeforeTheHighest] * WEIGHT_FACTOR * 9;
					WeightedSensorValues[2]=SensorValues[SensorWithHighestValue] * WEIGHT_FACTOR * 10;
					WeightedSensorValues[3]=SensorValues[SensorAfterTheHighest] * WEIGHT_FACTOR * 11;
					WeightedSensorValues[4]=SensorValues[SecondSensorAfterTheHighest] * WEIGHT_FACTOR * 12;
					break;
				default:
					WeightedSensorValues[0]=SensorValues[SecondSensorBeforeTheHighest] * WEIGHT_FACTOR * (SecondSensorBeforeTheHighest +3);
					WeightedSensorValues[1]=SensorValues[SensorBeforeTheHighest] * WEIGHT_FACTOR * (SensorBeforeTheHighest +3);
					WeightedSensorValues[2]=SensorValues[SensorWithHighestValue] * WEIGHT_FACTOR * (SensorWithHighestValue +3);
					WeightedSensorValues[3]=SensorValues[SensorAfterTheHighest] * WEIGHT_FACTOR * (SensorAfterTheHighest +3);
					WeightedSensorValues[4]=SensorValues[SecondSensorAfterTheHighest] * WEIGHT_FACTOR * (SecondSensorAfterTheHighest +3);
					break;
			}/* End switch (SensorWithHighestValue) */

			/* Keep a copy of the mean value from the previous interrupt. */
			PreviousMeanValue=MeanValue;

			/* Calculate Mean value */
			MeanValueNum=0;
			for(i=0;i<5;i++)
				MeanValueNum=MeanValueNum+WeightedSensorValues[i];

			MeanValueDen = SensorValues[SecondSensorBeforeTheHighest] + SensorValues[SensorBeforeTheHighest] + SensorValues[SensorWithHighestValue] + SensorValues[SensorAfterTheHighest] + SensorValues[SecondSensorAfterTheHighest];
			MeanValue=MeanValueNum/MeanValueDen;

			/************************
			* Calculate the offset
			************************/
			if(TouchwheelProperlyTouched==1)
			{
				if (PreviousSensorWithHighestValue==7 && SensorWithHighestValue==0)
					PositionOffset=MeanValue;
				else if (PreviousSensorWithHighestValue==0 && SensorWithHighestValue==7)
					PositionOffset=PreviousMeanValue;
				/* Clamp the offset if it goes to high */
				if(PositionOffset>OFFSET_POSITION_CLAMP)
					PositionOffset=OFFSET_POSITION_CLAMP;
			}

			/**************************
			* Update mean value fifo
			**************************/
			/* Calculate the mean value without the offset */
			MeanValueWithoutOffset = MeanValue-PositionOffset;

			if(MeanValueWithoutOffset<0)
				MeanValueWithoutOffset=0;
			/* The first time we touch we initialize the entire fifo to prevent a jump. */
			if(FirstTimeTouchWheelTouched==1)
				Initialize_Fifo(MeanValueFifo,SMALL_FIFOLENGTH, MeanValueWithoutOffset);
			else if(FirstTimeTouchWheelTouched==2)
				Move_Data_In_Fifo(MeanValueFifo, NULL, SMALL_FIFOLENGTH, MeanValueWithoutOffset, 0);

			/*******************************************************************
			* Calculate the ratio to scale down to NUMBER_OF_WANTED_POSITIONS
			*******************************************************************/
			if (PreviousSensorWithHighestValue==7 && SensorWithHighestValue==0)
			{
				/* Update the ratio */
				if(TouchwheelProperlyTouched==1)
					PositionRatio=((float)MeanValueFifo[1])/NUMBER_OF_WANTED_POSITIONS;
			}
			else if (PreviousSensorWithHighestValue==0 && SensorWithHighestValue==7)
			{
				/* Update the ratio */
				if(TouchwheelProperlyTouched==1)
					PositionRatio=((float)MeanValueFifo[0])/NUMBER_OF_WANTED_POSITIONS;
			}
			PositionOnTw=MeanValueWithoutOffset/PositionRatio;


			if(PositionOnTw>NUMBER_OF_WANTED_POSITIONS)
				PositionOnTw=NUMBER_OF_WANTED_POSITIONS;

			/**************************************************************
			* Record position on first touch and keep track of positions
			**************************************************************/
			if(FirstTimeTouchWheelTouched==1)
			{
				FirstTimeTouchWheelTouched=2;
				Initialize_Fifo(PositionFifo, SMALL_FIFOLENGTH, PositionOnTw);
				/* Keep track of the position on the first touch for calculating the relative position. */
				PositionOnFirstTouch = PositionOnTw;
				PositionOnFirstTouchForActivation = PositionOnTw;
			}
			else if(FirstTimeTouchWheelTouched==2)
				Move_Data_In_Fifo(PositionFifo, NULL, SMALL_FIFOLENGTH, PositionOnTw, 0);

			/*****************************************
			* Find the 12 o'clock absolute position
			*****************************************/
			if (TouchwheelProperlyTouched==1)
			{
				if (PreviousSensorWithHighestValue==7 && SensorWithHighestValue==0)
				{
					TwelveOclockPosition=PositionFifo[1];
					TwelveOclockDispRelatedToFirstTouch=PositionFifo[1];
				}
				else if (PreviousSensorWithHighestValue==0 && SensorWithHighestValue==7)
				{
					TwelveOclockPosition=PositionFifo[0];
					TwelveOclockDispRelatedToFirstTouch=PositionFifo[0];
				}
			}

			/********************************************/
			/* Prevent multiple taps on the scrollwheel */
			/********************************************/
			if (TouchwheelProperlyTouched==0)
			{
				/* Case where we have 2 fingers touching for a short amount of time */
				if(PreviousTouchError==1 && TouchError==0)
				{
					/* Need this otherwise "FirstTouchInitCounter" always remains "0" and FirstTouchInitCounter can never start counting. */
					MultiTapNoTouchCounterOnTw=T_NO_TOUCHING_MULTI_TAP+1;
					FirstTouchInitCounter=0;

					/* Need this otherwise, the dot goes through an intermediate position */
					FirstTimeTouchWheelTouched=0;
					MultiTapDetected=1;
			   	}
				/* Same thing here, if there were multiple taps but very short leaving only
				   one finger at a time on the touchwheel. */
				if (MultiTapNoTouchCounterOnTw<T_NO_TOUCHING_MULTI_TAP && MovementDetectedOnActivation==0)
				{
					/* Need this otherwise "FirstTouchInitCounter" always remains "0" and FirstTouchInitCounter can never start counting. */
					MultiTapNoTouchCounterOnTw=T_NO_TOUCHING_MULTI_TAP+1;
					MultiTapDetected=1;

					/* Need this otherwise, the dot goes through an intermediate position */
					FirstTimeTouchWheelTouched=0;
				}

				if (TouchwheelProperlyTouched==1)
				{
					/* Need that otherwise "FirstTouchInitCounter" always remains "0" and FirstTouchInitCounter can never start counting. */
					MultiTapNoTouchCounterOnTw=T_NO_TOUCHING_MULTI_TAP+1;
				}

				/* If multiple taps were detected and are now stopped, then we
				   initialize again the position on first touch and allow the display */
				if(FirstTouchInitCounter<=TIME_BEFORE_REINITIALISATION)
				{
					if(FirstTouchInitCounter==TIME_BEFORE_REINITIALISATION)
					{
						FirstTimeTouchWheelTouched=1;
						MultiTapDetected=0;
					}
					FirstTouchInitCounter++;
				}
			}
			else
				MultiTapDetected=0;

			/*********************************************************
			* Calculate the displacement related to the first touch
			*********************************************************/
			if ((DisplacementDetectedSinceActivation==0 ) && AllowDisplayAfterActivation==1)
			{
				if (PositionFifo[1]>96 && PositionFifo[0]<32) /* Clockwise */
					TwelveOclockPoint=1;
				else if (PositionFifo[0]>96 && PositionFifo[1]<32) /* counter clockwise */
					TwelveOclockPoint=2;

				switch (TwelveOclockPoint)
				{
					case 0:
						DispRelatedToFirstTouch=abs(PositionFifo[0]-PositionOnFirstTouchForActivation);
						break;
					case 1:
						DispRelatedToFirstTouch=TwelveOclockDispRelatedToFirstTouch+PositionFifo[0];
						break;
					case 2:
						DispRelatedToFirstTouch=TwelveOclockDispRelatedToFirstTouch+(NUMBER_OF_WANTED_POSITIONS-PositionFifo[0]);
						break;
				}
				if (DispRelatedToFirstTouch>NUMBER_OF_POSITIONS_TO_ACTIVATE)
					DisplacementDetectedSinceActivation=1;

				if (abs(DispRelatedToFirstTouch)>NumberOfPositionsAllowed)
				{
					TappingFlag=0;
				}
			}


			/*********************************************************************************************
			*
			********************* CODE FOR THE RELATIVE DISPLACEMENT WHILE SCROLLING ********************
			*
			*********************************************************************************************/
			if(MultiTapDetected==0 && MovementDetectedOnActivation==1 && DisplacementDetectedSinceActivation==1)
			{
				/* Catch 12.00 point */
				if (PositionFifo[1]>96 && PositionFifo[0]<32)
				{
					/* Clockwise */
                    TwelveOclockDisplacement = NUMBER_OF_WANTED_POSITIONS - PositionFifo[1] + PositionFifo[0];
                    TwelveOclockPointFound = 1;
				}
				else if (PositionFifo[0]>96 && PositionFifo[1]<32)
				{
					/* counter clockwise */
                    TwelveOclockDisplacement = -(NUMBER_OF_WANTED_POSITIONS - PositionFifo[0] + PositionFifo[1]);
                    TwelveOclockPointFound = 2;
				}

				/* Once we've caught the 12.00 point, we make sure that the relative position is greater than
        	       SCROLLING_RESOLUTION. If it is not, we keep looking at the absolute position until the
				   relative displacement reaches SCROLLING_RESOLUTION Once it does, we clear all the flags. */
				if (TwelveOclockPointFound==1)
				{
					/* Clockwise */
	                if (TwelveOclockDisplacement<DisplayItemsResolution)
					{
						/* Calculate relative displacement at 12.00 */
	                    RelativeDisplacement = TwelveOclockDisplacement + PositionFifo[0];
						/* Relative disp at 12.00 is smaller than the scrolling resolution
						   therefore keep calculating the relative displacement until it reaches
						   the scrolling resolution */
	                    if (abs(RelativeDisplacement)>=DisplayItemsResolution)
						{
	                        TwelveOclockPointFound=0;
	                        TwelveOclockDisplacement=0;
	                    }
	                }
					else
					{
						/* Relative disp at 12.00 is greater than the scrolling resolution
						   therefore clear all the flags */
	                    TwelveOclockPointFound=0;
	                    RelativeDisplacement=TwelveOclockDisplacement;
	                    TwelveOclockDisplacement=0;
	                }
	            }
	            else if (TwelveOclockPointFound==2)
				{
					/* counter clockwise */
	                if (abs(TwelveOclockDisplacement) < DisplayItemsResolution)
					{
						/* Calculate relative displacement at 12.00 */
						RelativeDisplacement=TwelveOclockDisplacement-(NUMBER_OF_WANTED_POSITIONS - PositionFifo[0]);
	                    if (abs(RelativeDisplacement)>=DisplayItemsResolution)
						{
	                        TwelveOclockPointFound=0;
	                        TwelveOclockDisplacement=0;
	                    }
					}
	                else
					{
						/* Relative disp at 12.00 is greater than the scrolling resolution
						   therefore clear all the flags */
	                    TwelveOclockPointFound=0;
	                    RelativeDisplacement=TwelveOclockDisplacement;
	                    TwelveOclockDisplacement=0;
					}
				}
	            else
				{
					/* Relative displacement anywhere else on the disc. */
					if (FirstTimeTouchWheelTouched==2)
					{
						tempResult = PositionFifo[0];
						tempResult = tempResult - PositionOnFirstTouch;
    	                RelativeDisplacement = tempResult;
					}
				}

				/* scroll up or down */
				if (abs(RelativeDisplacement) >= DisplayItemsResolution)
				{
					PositionOnFirstTouch = PositionFifo[0];
					if (RelativeDisplacement > 0)
					{
						if(MultiTapDetected==0 && MovementDetectedOnActivation==1 && LiftOffDetected==0)
						{
							if (UpdateDownOnce==1)
							{
								/* Go down */
								UpdateDownOnce=0;
								UpdateUpOnce=1;
								ScrollWheelStatus &= 0xCFFF;
								ScrollWheelStatus |= 0x1000;

								Fill_Line(CurrentLineNumber, true);

								if( CurrentLineNumber != 239 )
									CurrentLineNumber++;
							}
						}
						else
						{	/* Stay static */
							ScrollWheelStatus &= 0xCFFF;
						}
					}
					else if (RelativeDisplacement < 0)
					{
						if(MultiTapDetected==0 && MovementDetectedOnActivation==1 && LiftOffDetected==0)
						{
							if (UpdateUpOnce==1)
							{
								/* Go up */
								UpdateUpOnce=0;
								UpdateDownOnce=1;
								ScrollWheelStatus &= 0xCFFF;
								ScrollWheelStatus |= 0x2000;

								Fill_Line(CurrentLineNumber, false);

								if( CurrentLineNumber != 0 )
									CurrentLineNumber--;
							}
						}
						else
						{	/* Stay static */
							ScrollWheelStatus &= 0xCFFF;
						}
					}
				}
				else
				{
					/* Stay static */
					UpdateDownOnce=1;
					UpdateUpOnce=1;
					ScrollWheelStatus &= 0xCFFF;
				}
			}
			else
			{
				/* Stay static */
				UpdateDownOnce=1;
				UpdateUpOnce=1;
				ScrollWheelStatus &= 0xCFFF;
			}
		} /* End if((TouchError & 0x01)!=0x01) */

		/************************************
		* Clear the tap if we're scrolling
		************************************/
		/* We have a new position, if it is different from the previous one and we are still within the
		   the tapping time, then we check the positions. If we are moving, then we clear the tapping bit. */
		if( ((TouchError& 0x1)!=0x1) && ScrollWheelTouchDownCounter<T_MAX_TOUCHING)
		{
			if(MovementDetectedOnActivation==1)
			{
				ScrollWheelTouchDownCounter=T_MAX_TOUCHING+1;
				TappingFlag=0; /* Clear tapping bit on slider */
				EnableTapDisplayOnTw=0;	/* We're moving, so don't display the tap; */
				MultiTapDetected=0;
			}
			else
				EnableTapDisplayOnTw=1;	/* We haven't moved by far enough, so a tap is still valid */
		}

		/***************************
		* Format the position data
		****************************/
		ScrollWheelStatus &= 0xF3FF;
		ScrollWheelStatus |= ((TouchError <<2)<<8);

		if (TouchwheelFlag==1)
		{
			/* Compute position registers */
			if (MultiTapDetected==0 && LiftOffDetected==0 && AllowDisplayAfterActivation==1 && ((TouchError & 0x1)!=0x1))
			{
				ScrollWheelStatus &= 0x7F00;
				/* Return absolute positions. We use element 1 to hide the change of position when lifting off. */
				ScrollWheelStatus = ScrollWheelStatus | 0x8000 | PositionFifo[1];
			}
		}
		else	/* Not touching... */
		{
			/* Clear finger valid bit and go up go down commands */
			ScrollWheelStatus &= 0x0FFF;
			if(TappingFlag==1)
			{
				ScrollWheelStatus |= 0x4000;
			}
		}

	}/* End if(InterruptCounterForSliderInitialisations>=NB_OF_INT) */
}

/****************************************************************************
*   Function:    Service_AD7147_Isr
*   Description: Function called by the AD7147 ISR. Anything that must be
* 				 executed during the ISR needs to be done here.
******************************************************************************/
static void Service_AD7147_Isr(void)
{
	/* Read thresholds and proximity registers */
	Read_AD7147(STAGE_LOW_LIMIT_INT, &AD7147Registers[STAGE_LOW_LIMIT_INT], 3);

	/* depending on what was pressed( PB or scrollwheel ) take the
	   appropriate action */
	if( AD7147Registers[STAGE_HIGH_LIMIT_INT] & 0xF00 )
		Process_PB_Touch();
	else
		Process_Scroll_Wheel_Touch();

}

/****************************************************************************
*   Function:    Move_Data_In_Fifo
*   Description: Function that shifts the data in the fifo. There are 2 types
*				 of Fifos: "unsigned short" and "long int", when calling them,
*				 we differentiate them using using the "FifoType" parameter
******************************************************************************/
static void Move_Data_In_Fifo(unsigned short *FifoName, int *SignedFifo, const unsigned char FifoLength, const unsigned short newData, const bit FifoType)
{
	unsigned char i;
	if(FifoType==0)
	{
		for(i=1; i<FifoLength; i++)
		    FifoName[FifoLength-i] = FifoName[FifoLength-i-1];
		FifoName[0]=newData;
	}
	else
	{
		for(i=1; i<FifoLength; i++)
		    SignedFifo[FifoLength-i] = SignedFifo[FifoLength-i-1];
		SignedFifo[0]=newData;
	}
}

/****************************************************************************
*   Function:    Initialize_Fifo
*   Description: Instead of having several for loops in the code to initialise
				 an array, this function was created instead
******************************************************************************/
static void Initialize_Fifo(unsigned short *FifoName, const unsigned char FifoLength, const unsigned short InitValue)
{
	unsigned char i;

	for(i=0;i<FifoLength;i++)
		FifoName[i]=InitValue;
}

/****************************************************************************
*   Function:    Find_Highest_And_Lowest_Stages_Used
*   Description: Function that finds which is the highest and which is the
*				 lowest sensor touched during a scroll.  If there is a big
*				 finger touching the sensor, then the BigFingerTouching flag
*				 is set. if there is more than one finger touching, then
*				 TwoFingerTouching flag is set. If any of these 2 flags
*				 are set, the function returns an error otherwise 0 for normal
*			 	 operation.
******************************************************************************/
static unsigned char Find_Highest_And_Lowest_Stages_Used(const unsigned short InterruptStatusRegister, const unsigned short LowestStageOfTheSensor, const unsigned short HighestStageOfTheSensor, const unsigned char NumberOfStagesUsed, const unsigned char BigFingerLevel, unsigned char *LowestSensorTouched, unsigned char *HighestSensorTouched)
{
	unsigned short  ShiftValue;
	unsigned char  i,  InterruptBitCounter;
	bit LowestSensorTouchedFound, HighestSensorTouchedFound;
	bit TwoFingerTouching, BigFingerTouching;

	/* Initialization */
	LowestSensorTouchedFound=0;
	HighestSensorTouchedFound=0;
	*LowestSensorTouched=0xFF;
	*HighestSensorTouched=0xFF;
	InterruptBitCounter=0;
	TwoFingerTouching=0;
	BigFingerTouching=0;

	if(((InterruptStatusRegister & LowestStageOfTheSensor) == LowestStageOfTheSensor) && ((InterruptStatusRegister & HighestStageOfTheSensor) == HighestStageOfTheSensor))
	{
		/*************************************************************************
		** Touchwheel specific
		*****************************
		** Comment out the whole if statement above for a slider or any others.
		*************************************************************************/

		/*Start from the highest stage and walk back down to the lowest stage. The value of the
		  lowest sensor touched will be bigger than the value of the highest sensor touched. */
		ShiftValue=HighestStageOfTheSensor;
		for(i=NumberOfStagesUsed;i!=0;i--)
		{
			if(((InterruptStatusRegister & ShiftValue) == 0) && LowestSensorTouchedFound==0)
			{
				/* Lowest sensor touched is found here */
				*LowestSensorTouched=i;
				LowestSensorTouchedFound=1;
			}
			else if((InterruptStatusRegister & ShiftValue) == ShiftValue)
			{
				InterruptBitCounter++;
				if (LowestSensorTouchedFound==1 && HighestSensorTouchedFound==0)
				{
					/* Highest sensor touched is found here */
					*HighestSensorTouched=i-1;
					HighestSensorTouchedFound=1;
				}
			}
			/* Code for detecting if there are 2 fingers on the entire sensor */
			if (LowestSensorTouchedFound==1 && HighestSensorTouchedFound==1 && ((InterruptStatusRegister & ShiftValue) == 0) && i<(*LowestSensorTouched))
				TwoFingerTouching=1;

			ShiftValue=ShiftValue>>1;
		}
	}
	else
	{
		/******************************
		* Code common to all sensors
		******************************/
		ShiftValue=LowestStageOfTheSensor;
		for(i=0;i<NumberOfStagesUsed;i++)
		{
			/* Found the lowest sensor touched */
			if((InterruptStatusRegister & ShiftValue) == ShiftValue)
			{
				if(LowestSensorTouchedFound==0)
				{
					/* Lowest sensor touched is found here */
					*LowestSensorTouched=i;
					LowestSensorTouchedFound=1;
				}
				/* If last sensor is set, then it is also the highest sensor touched */
				if(i==(NumberOfStagesUsed-1) && LowestSensorTouchedFound==1 && HighestSensorTouchedFound==0)
				{
					*HighestSensorTouched=i;
					HighestSensorTouchedFound=1;
				}
			}
			/* Found the highest sensor touched */
			else if(((InterruptStatusRegister & ShiftValue) == 0) && LowestSensorTouchedFound==1 && HighestSensorTouchedFound==0)
			{
				/* Highest sensor touched is found here */
				*HighestSensorTouched=i-1;
				HighestSensorTouchedFound=1;
			}
			ShiftValue=ShiftValue<<1;
		}

		/* Code for detecting if there are 2 fingers on the entire sensor and if there is a big
		   finger touching it. We count the number of interrupts set and if it is greater than
		   "BigFingerLevel", then we set the "BigFingerTouching" flag. */
		ShiftValue=LowestStageOfTheSensor;
		for(i=0;i<NumberOfStagesUsed;i++)
		{
			if((InterruptStatusRegister & ShiftValue)==ShiftValue)
			{
				InterruptBitCounter++;
				if((i>(*HighestSensorTouched)) || (i<(*LowestSensorTouched)))
					TwoFingerTouching=1;
			}
			ShiftValue=ShiftValue<<1;
		}
	}
	if(InterruptBitCounter>=BigFingerLevel)
		BigFingerTouching=1;

	/* Return error code */
	return (((unsigned char)TwoFingerTouching) | (((unsigned char)BigFingerTouching)<<1));
}

/****************************************************************************
*   Function:    Initialize_TouchWheel
*   Description: Function that initialise the touchwheel. It is called on
*				 power up and when calibrating all the sensors
******************************************************************************/
static void Initialize_Touch_Wheel(unsigned short *AmbientVals, unsigned short *MaxAvgVals)
{
	unsigned char i;

	/* Initialise the scaled down value of the distance between the current value - ambient value. */
	for(i=0;i<NB_OF_SENSORS_FOR_TW;i++)
	{
	    /* Calculate the resolution */
		Resolutions[i]=(MaxAvgVals[i]-AmbientVals[i])/SENSOR_RESOLUTION;
		MaxSensorValues[i] = SENSOR_RESOLUTION;
		SensorValues[i]=0;
		/* Initialise SensorValuesFifo */
		SensorValuesFifo[i]=0;
		SensorValuesFifo[i+NB_OF_SENSORS_FOR_TW]=0;
	}
	PositionRatio=INITIAL_POSITION_RATIO;
	PositionOffset=OFFSET_POSITION_CLAMP;
	MultiTapDetected=0;
}

void TEST_LCD_CAPTOUCH(void)
{
	unsigned short usDevId;
	unsigned short ButtonStatus;
	int i = 0;

	/* make sure our interrupt is masked */
	Disable_INT();

	/* turn on the LCD backlight */
	Write_AD7879(CONTROL_REG_2, 0x2000);

	/* reset TWI */
	ad7147_Reset_TWI();

	/* initialize interrupts */
	Init_AD7147_Interrupt();

	/* configure the stage buffers */
	Config_AD7147();

	/* reset which buttons were pressed */
	ButtonPressed = 0;

	/* configure LCD */
	/* REV = 1, TB = 1, BGR = 0 */
	Select_LQ035Q1DH02_Register(0x01);
	Write_LQ035Q1DH02_Data(0x22EF);

	/* Set SHUT(Bit 0) to 0 which takes the LCD out of sleep mode
	   because it is by default in sleep mode via a resistor
	   Set CM(bit 8) to 0 for 262k color mode */
	Select_LQ035Q1DH02_Register(0x11);
	Write_LQ035Q1DH02_Data(0x0000);

	/* reset the index */
	i = 0;

	/* start the color at all black */
	Set_LCD_Color(RGB565_BLACK, 0);

    /* configure our buffers to pad lines for the front porch */
    DummyBuffer[0].pNext             = &DummyBuffer[1];   /* chain to next buffer in the list */
    DummyBuffer[0].StartAddress      = TempFrame;
    DummyBuffer[0].XCount            = H_ACTPIX;
    DummyBuffer[0].XModify           = 2;
    DummyBuffer[0].YCount            = 2;
    DummyBuffer[0].YModify           = 2;
    DummyBuffer[0].Config           	=	DMAEN 		|	/* enable DMA */
											WDSIZE_16	|	/* WDSIZE=01, 16 bit */
											DMA2D 		|	/* DMA2D=1. 2D */
											NDSIZE_9	|	/* NDSIZE=9 */
									  		FLOW_LARGE;		/* large list descriptor mode */

	DummyBuffer[1].pNext             = &Buffer1[0];   /* chain to next buffer in the list */
    DummyBuffer[1].StartAddress      = TempFrame;
    DummyBuffer[1].XCount            = H_ACTPIX;
    DummyBuffer[1].XModify           = 2;
    DummyBuffer[1].YCount            = 2;
    DummyBuffer[1].YModify           = 2;
    DummyBuffer[1].Config           	=	DMAEN 		|	/* enable DMA */
											WDSIZE_16	|	/* WDSIZE=01, 16 bit */
											DMA2D 		|	/* DMA2D=1. 2D */
											NDSIZE_9	|	/* NDSIZE=9 */
									  		FLOW_LARGE;		/* large list descriptor mode */


	/* FOR (Number of output 2D buffers) */
    for (i = 0; i < LCD_NUM_FRAMES_DISPLAY; i++)
    {
    	Buffer1[i].pNext             = &Buffer1[i + 1];   /* chain to next buffer in the list */
    	Buffer1[i].StartAddress      = Frame0;
        Buffer1[i].XCount            = H_ACTPIX;
        Buffer1[i].XModify           = 2;
        Buffer1[i].YCount            = V_LINES;
        Buffer1[i].YModify           = 2;
        Buffer1[i].Config           	=	DMAEN 		|	/* enable DMA */
											WDSIZE_16	|	/* WDSIZE=01, 16 bit */
											DMA2D 		|	/* DMA2D=1. 2D */
											NDSIZE_9	|	/* NDSIZE=9 */
									  		FLOW_LARGE;		/* large list descriptor mode */
    }

    /* make the buffer loop back around */
	Buffer1[LCD_NUM_FRAMES_DISPLAY - 1].pNext = &Buffer1[0];

	LQ035Q1DH02_Init_PPI_Ints();	/* initialize PPI interrupts */

	LQ035Q1DH02_Init_TIMER0();			/* init timer 0( horizontal FS ) */
	LQ035Q1DH02_Init_TIMER1();			/* init timer 1( vertical FS ) */
	LQ035Q1DH02_Init_PPI();				/* initialize PPI */

	LQ035Q1DH02_Init_DMA(DummyBuffer);	/* initialize the DMA */

	/* start PPI */
    LQ035Q1DH02_Enable_PPI();

	/* Frame sync 2 (VS) needs to start at least one PPI clk earlier */
	LQ035Q1DH02_Enable_TIMER1();

	/* now start frame sync 1 */
	LQ035Q1DH02_Enable_TIMER0();

	/**********************
	** Initialize variables
	***********************/
	InterruptCounterForTouchwheelInitialisation=0;
	InterruptCounterForThresIntMode=NUMBER_OF_INTS_BEFORE_THRESH_INT_MODE;

	/* Initialize activation variables */
	FirstTimeTouchWheelTouched=0;
	ScrollWheelTouchDownCounter=0;
	TouchwheelProperlyTouched=0;
	DisplayItemsResolution=(NUMBER_OF_WANTED_POSITIONS+1)/DISPLAY_ITEMS_CONSTANT;
	NumberOfPositionsAllowed=DisplayItemsResolution*1.5;

	/* assign ISRs to interrupt vectors  */
	Assign_AD7147_IntVector(CAP_TOUCHIRQ_ISR);

	/* unmask our interrupt */
	Enable_INT();

	while( 1 )
	{
		asm("nop;");
		asm("nop;");
		asm("nop;");
	}


}//end main


#ifdef _STANDALONE_

/* PLL_CTL Macros (Only Use With Logic OR While Setting Lower Order Bits)			*/
#define	SET_MSEL(x)		(((x)&0x3F) << 0x9)	/* Set MSEL = 0-63 --> VCO = CLKIN*MSEL		*/
/* PLL_DIV Macros														*/
#define SET_SSEL(x)			((x)&0xF)	/* Set SSEL = 0-15 --> SCLK = VCO/SSEL	*/
#define SET_CSEL(x)			(((x)&0x3) << 0x4) /* Set CSEL = 0-3 --> CCLK = VCO/(2^CSEL) */

int main(void)
{
	int bPassed = 1;
	int count = 0;

	*pSIC_IWR0 |= 0x1;			/* enable PLL wakeup */
	*pPLL_CTL = SET_MSEL(16);	/* (25MHz Xtal x (MSEL=16))::CCLK=400MHz		*/

	idle();

	*pPLL_DIV = SET_SSEL(5);	/* (400MHz/(SSEL=5))::SCLK=80MHz				*/
	ssync();

	TEST_LCD_CAPTOUCH();

	return bPassed;
}

#endif


