/* ----------------------------------------------------------------- */
/* 'ZUserInputClass.cc'									    */
/* 												         */
/* 													    */
/* 	last modified 07/04/2003								    */
/* 	wraps functions for possibe user input and desenifies it	    */
/* 	(Make sure servo-power is switched on to power IR-receiver)	    */
/* 	(C) Jochen Zimmermann								    */
/* 												         */
/* 												         */
/* ----------------------------------------------------------------- */

#include "ZHeaders.h"
/*
//Headerfile is included by ZHeaders.h
#include "ZUserInputClass.h"
*/


//Single Instance is globally created
UserInput UserInput::SingleInstance;


//constructor
//initialises members
UserInput::UserInput()
{
	bufferpos=0;
	for(int i=0;i<SIZEOFINPUTBUFFER;i++)
	{
		inputbuffer[i][0]=0;
		inputbuffer[i][1]=0;
	}
}

//instance retriever
UserInput* UserInput::GetTheInstance()
{
	return &SingleInstance;
}


//initialising keys, IR, and member
int UserInput::Init()
{
	bufferpos=0;
	for(int i=0;i<SIZEOFINPUTBUFFER;i++)
	{
		inputbuffer[i][0]=0;
		inputbuffer[i][1]=0;
	}
	return IRTVInit(SPACE_CODE,15,0,0x3ff,DEFAULT_MODE,1,10);
}


//read if input is done either by keys or remote-control
int UserInput::Read()							//not waiting
{
	int button,key;
	button=IRTVPressed();
	key=KEYRead();	
	if (button+key) return AppendToBuffer(button+key);
	else 		 return 0; 
}


//wait for any key to be pressed or time elapses
int UserInput::Wait()			
{
	int pressed=0;
	while( !( pressed=Read() ) );
	return pressed;
}


//wait for any key to be pressed or time elapses
int UserInput::WaitTime(int time)			
{
	int pressed=0;
	int count=0;
	if(time>0)
	{
		count=OSGetCount();
		OSWait(1);
		//LCDPrintf("en read");
		while( !( pressed=Read() ) && ((-time)<(count-OSGetCount())) );//waiting for any KEY to be pressed or time elapsed
	}
	else
	{
		while(!(pressed=Read()));//waiting for any KEY to be pressed
	}
	return pressed;
}


//wait for special key to be pressed
int UserInput::Wait(int specified_key)	//wait for special Key (does not increas Buffer)
{
	int pressed;
	while(Read()!=specified_key);	
	return GetFromBuffer();
}


//empty local buffer
int UserInput::Flush()							//empty buffer
{
	bufferpos=0;
	for(int i=0;i<SIZEOFINPUTBUFFER;i++)
	{
		inputbuffer[i][0]=0;
		inputbuffer[i][1]=0;
	}
	IRTVFlush();
	return 0;
}


//buffer appending
int UserInput::AppendToBuffer(int value)
{
	bufferpos++;
	if(bufferpos>=SIZEOFINPUTBUFFER) bufferpos=0;
	inputbuffer[bufferpos][0]=value;
	inputbuffer[bufferpos][1]=OSGetCount();
	if(!WrapMultiReadings())	return value;
	else return 0;
}


//check last buffer 
int	UserInput::GetFromBuffer()
{
	int old=bufferpos;
	bufferpos--;
	if(bufferpos<0) bufferpos=SIZEOFINPUTBUFFER-1;
	return inputbuffer[old][0];
}


//delete fast double-reads
bool UserInput::WrapMultiReadings()
{
	int pred,timegap;
	
	pred=bufferpos-1;
	timegap=50;	//in 1/100 seconds (e.g. 0: timegap <= 1/100 sec, 1: timegap <= 2/100 sec, aso)
	
	if(pred<0) pred=SIZEOFINPUTBUFFER-1;	//loopback listpointer
	
	if(	
		(inputbuffer[bufferpos][0]==inputbuffer[pred][0]) 		//same value
			&& 											//in specified
		((inputbuffer[bufferpos][1]-inputbuffer[pred][1])<=timegap)	//period
	  )
	{
		bufferpos=pred;
		WrapMultiReadings();
		return true;	//wrapped something means there was a double read
	}
	else return false;	//no double read ok
}