/****************************************************************************
*
* $RCSfile: Timer.c $
* $Revision: 1.1 $
* $Date: 1997/07/06 03:07:32 $
* $Author: ssolie $
*
*****************************************************************************
*
* Copyright (c) 1997 Software Evolution.  All Rights Reserved.
*
*****************************************************************************
*
* Timer.c -- Timer object source code
*
* This file contains the source code for Timer objects.
*/

#include <devices/timer.h>
#include <exec/memory.h>

#include <proto/exec.h>

#include "Debug.h"
#include "Timer.h"


/*** Global variables ***/
IMPORT struct ExecBase *SysBase;


/*** Local constants ***/
const STRPTR TIMER_DEV = "timer.device";


/*** Local data types ***/
struct TimerClass {
	struct MsgPort *msg_port;		/* message port */
	struct timerequest *time_req;	/* I/O request message */
	BOOL running;					/* running flag */
};


/*
 * newTimer -- Create Timer object
 *
 * This function is used to create a new Timer object.  Returns a reference
 * to the timer or NULL on error.
 */
Timer newTimer(VOID)
{
	Timer this;
	BYTE dev_result;

	D(bug("newTimer()\n"));

	this = AllocVec(sizeof(struct TimerClass), MEMF_CLEAR);
	if ( this == NULL )
		return(NULL);

	this->msg_port = CreateMsgPort();
	this->time_req = (struct timerequest*)
		CreateIORequest(this->msg_port, sizeof(struct timerequest));
	if ( this->time_req == NULL )  {
		deleteTimer(this);
		return(NULL);
	}

	dev_result = OpenDevice(TIMER_DEV, UNIT_MICROHZ,
		(struct IORequest*)this->time_req, NULL);
	if ( dev_result != 0 )  {
		deleteTimer(this);
		return(NULL);
	}

	this->running = FALSE;

	return(this);
}


/*
 * deleteTimer -- Delete Timer object
 *
 * This function used to delete a Timer object.
 */
VOID deleteTimer(Timer this)
{
	D(bug("deleteTimer(%08lx)\n", this));

	if ( this != NULL )  {
		if ( this->time_req != NULL )  {
			AbortIO(this->time_req);
			WaitIO(this->time_req);
			CloseDevice(this->time_req);
		}

		DeleteIORequest(this->time_req);
		DeleteMsgPort(this->msg_port);
		FreeVec(this);
	}
}


/*
 * startTimer -- Start timer
 *
 * This function is used to start a Timer object.  The timer will expire
 * at or after the specified number of seconds.
 */
VOID startTimer(Timer this, ULONG seconds)
{
	D(bug("startTimer(%08lx, %lu)\n", this, seconds));

	if ( this == NULL || seconds == 0 )
		return;

	if ( !this->running )  {
		this->time_req->tr_node.io_Command	= TR_ADDREQUEST;
		this->time_req->tr_time.tv_secs		= seconds;
		this->time_req->tr_time.tv_micro	= 0;
		SendIO(this->time_req);

		this->running = TRUE;
	}
}


/*
 * stopTimer -- Stop timer
 *
 * This function is used to stop a Timer object.  Once the timer has been
 * stopped, it may be started again.
 */
VOID stopTimer(Timer this)
{
	D(bug("stopTimer(%08lx)\n", this));

	if ( this == NULL )
		return;

	if ( this->running )  {
		AbortIO(this->time_req);
		WaitIO(this->time_req);

		this->running = FALSE;
	}
}


/*
 * handleTimerSignal -- Handle Timer object signal
 *
 * This function handles a signal for a Timer object.  You should always
 * call this function after receiving a timer signal.  This function will
 * not return until the timer request has completely finished.
 */
VOID handleTimerSignal(Timer this)
{
	D(bug("handleTimerSignal(%08lx)\n", this));

	if ( this == NULL )
		return;

	if ( this->running )  {
		WaitIO(this->time_req);

		this->running = FALSE;
	}
}


/*
 * getTimerSignal -- Get Timer object signal
 *
 * This function will get the Timer object signal.  Returns the signal
 * that this timer is using or NULL on error.
 */
ULONG getTimerSignal(Timer this)
{
	ULONG signal;

	D(bug("getTimerSignal(%08lx)\n", this));

	if ( this == NULL )
		signal = NULL;
	else
		signal = (ULONG)1 << this->msg_port->mp_SigBit;

	return(signal);
}
