
#include "fireworks.h"
#include "fireworks_protos.h"

int __interrupt __saveds VBlankInterface( void );

extern struct Library *TimerBase;

struct EClockVal eclock;
ULONG E_Freq;
UWORD E_Freq_1000;

/* Interrupt stuff */

struct Interrupt VertBlank =
{
	NULL,NULL,NT_INTERRUPT,-60,"Fireworks VBlank",	/* node, pri = -60 */
	NULL,											/* data ptr, same as inputevent */
	(void *)VBlankInterface							/* code ptr */
};

struct EClockVal stampeclock;
BOOL Watch;
ULONG IdleCount;


/*-------------------*/
/* Open timer device */
/*-------------------*/

struct timerequest *OpenTimer(void)
{
	BOOL Success = FALSE;
	
	struct MsgPort *reply = NULL;
	struct timerequest *treq = NULL;
	
	if (!(reply = CreateMsgPort()))
	{
		Message("Unable to create timer port!",NULL);
	}
	else
	{
		if (!(treq = CreateIORequest(reply, sizeof(struct timerequest))))
		{
			Message("Unable to create timer request!",NULL);
		}
		else
		{
			if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest*)treq,0))
			{
				Message("Timer: Cannot open timer.device (UNIT_VBLANK).",NULL);
			}
			else
			{
				TimerBase = (struct Library*)treq->tr_node.io_Device;
				
				E_Freq      = ReadEClock(&eclock);
				E_Freq_1000 = E_Freq / 1000;
				
				Success = TRUE;
			}
		}
	}
	
	if (!Success)
	{
		if (TimerBase)
		{
			CloseDevice((struct IORequest*)treq);
			TimerBase = NULL;
		}
		
		if (treq)
		{
			DeleteIORequest(treq);
			treq = NULL;
		}
		
		if (reply)
		{
			DeleteMsgPort(reply);
			reply = NULL;
		}
	}
	
	return(treq);
}



/*--------------------*/
/* Close timer device */
/*--------------------*/

void CloseTimer(struct timerequest *treq)
{
	struct MsgPort *reply = NULL;
	
	if (treq)
	{
		if (treq->tr_node.io_Device)
		{
			CloseDevice((struct IORequest*)treq);
			TimerBase = NULL;
		}
		
		reply = treq->tr_node.io_Message.mn_ReplyPort;
		
		DeleteIORequest(treq);
		treq = NULL;
	}
	
	if (reply)
	{
		DeleteMsgPort(reply);
		reply = NULL;
	}
}


/*----------------*/
/* Get Time Delta */
/*----------------*/

/* This function returns the time difference in milliseconds */
/* to the time it was called last                            */

ULONG GetTimeDelta(void)
{
	ULONG delta;
	ULONG old_lo = eclock.ev_lo;
	
	ReadEClock(&eclock);
	
	delta = 1000 * (eclock.ev_lo - old_lo) / E_Freq;
	
	return(delta);
}


/*------------------------*/
/* How Old Is Time Stamp? */
/*------------------------*/

/* This function returns the age of a time stamp in milliseconds */
/* relatively to the time GetTimeDelta() was called last         */

LONG HowOldIsTimestamp(ULONG timestamp)
{
	LONG delta = ((LONG)eclock.ev_lo - (LONG)timestamp) / (WORD)E_Freq_1000;
	
	return(delta);
}



/*----------------------------------------*/
/* VBR Interrupt handler (Watchdog timer) */
/*----------------------------------------*/

int __interrupt __saveds VBlankInterface( void )
{
	ReadEClock(&stampeclock);		/* for timestamping */
	
	if (Watch)
	{
		if (IdleCount++ >= (50/MIN_FPS))
		{
			SetTaskPri(MyTask, HIGHPRI);
			IdleCount = 0;
		}
	}
	
	return 0;                      /* server chain continues */
}
