/**************************************
*  TIMER.C  08/04/90
*  Written by Timm Martin
*  This source code is public domain.
***************************************/

#include <devices/timer.h>
#include <exec/ports.h>
#include <exec/types.h>
#include <functions.h>
#include "timer.h"

/********************
*  SHARED VARIABLES
*********************/

long                timer_error = 1;
struct timerequest  timer_req;
struct MsgPort *    timer_port = NULL;  /* GLOBAL */

/***************
*  TIMER ABORT
****************/

/*
This function cancels an existing time request.
*/

void timer_abort( void )
{
  AbortIO( &timer_req.tr_node );
  Wait( 1L<<timer_port->mp_SigBit );
  GetMsg( timer_port );
}

/***************
*  TIMER CLOSE
****************/

/*
This function closes the timer device and deletes the timer port.
*/

void timer_close( void )
{
  if (!timer_error)
  {
    CloseDevice( (struct IORequest *)&timer_req );
    timer_error = NULL;
  }
  if (timer_port)
  {
    DeletePort( timer_port );
    timer_port = NULL;
  }
}

/**************
*  TIMER OPEN
***************/

/*
This function opens the timer device and initializes it.
*/

BOOL timer_open( void )
{
  if (!(timer_port = CreatePort( NULL, 0L )) ||
      (timer_error = OpenDevice( TIMERNAME, UNIT_VBLANK,
          (struct IORequest *)&timer_req, NULL )))
    return (0);

  timer_req.tr_node.io_Message.mn_ReplyPort = timer_port;
  timer_req.tr_node.io_Command = TR_ADDREQUEST;
  timer_req.tr_node.io_Flags = 0;
  return (1);
}

/***************
*  TIMER START
****************/

/*
This function issues a request to the timer device to notify the program
in the specified number of microseconds.  This function does not wait for
a reply from the timer device.
*/

void timer_start( long micros )
{
  long secs;

  /* a bug in Kickstart v1.3 requires this check */
  if (micros < 2) return;

  secs = micros / MICROS_PER_SEC;
  micros %= MICROS_PER_SEC;

  timer_req.tr_time.tv_secs  = secs;
  timer_req.tr_time.tv_micro = micros;
  SendIO( &timer_req.tr_node );
}

/**************
*  TIMER TEST
***************/

/*
This function returns whether the last timer request has been satisfied.
*/

BOOL timer_test( void )
{
  return (GetMsg( timer_port ) != NULL);
}

/**************
*  TIMER WAIT
***************/

/*
This function waits for the specified number of microseconds.
*/

#define MICROS_PER_SEC 1000000L

void timer_wait( long micros )
{
  long secs;

  /* a bug in Kickstart v1.3 requires this check */
  if (micros < 2) return;

  secs = micros / MICROS_PER_SEC;
  micros %= MICROS_PER_SEC;

  timer_req.tr_time.tv_secs  = secs;
  timer_req.tr_time.tv_micro = micros;
  SendIO( &timer_req.tr_node );

  /* wait until time is up */
  Wait( 1L<<timer_port->mp_SigBit );
  GetMsg( timer_port );
}
