/*
 * This file implements a running millisecond timer using one of
 * the Amiga's hardware timers.
 *
 * This file must be compiled with Lattice -b0 and -v options.
 *
 * Alan Bland, August 1988
 * Updated June 1990 to follow Amiga Mail guidelines.
 * Ugly hacks added October 1991 for power glove stuff.
 * timer.h added March 1992 by Ethan Dicks <erd@kumiss.UUCP>
 */

#include <exec/types.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <hardware/cia.h>
#include <resources/cia.h>

#include <proto/exec.h>

#include "timer.h"

static volatile int times_up;
extern struct CIA ciab;
static struct Library *CIAResource;
static struct Interrupt interrupt;
static UBYTE interrupting;

void closetimer(void);

void
fatal(char *s)
{
	printf("fatal error: %s\n", s);
	closetimer();
	exit(1);
}

void
timerhandler()
{
	/* hardware timer interrupt */
	times_up = 1;
}

void
timersleep(long ticks)
{
	times_up = 0;

	ticks -= 8; if (ticks <= 0) { times_up=1; return; } /* yucko */

	/* 1.397 usec * n */
	ciab.ciatblo = ticks & 0xff;
	ciab.ciatbhi = (ticks>>8) & 0xff;

	/* one-shot */
	ciab.ciacrb |= CIACRBF_RUNMODE | CIACRBF_LOAD | CIACRBF_START;

	while (!times_up) {}
}

void
opentimer()
{
	static char* timername = "glove.timer";

	/* install interrupt handler */
	CIAResource = OpenResource(CIABNAME);
	if (CIAResource == NULL) fatal("can't get timer resource");

	interrupt.is_Node.ln_Type = NT_INTERRUPT;
	interrupt.is_Node.ln_Pri = 127;
	interrupt.is_Node.ln_Name = timername;
	interrupt.is_Data = NULL;
	interrupt.is_Code = timerhandler;
	if (AddICRVector(CIAResource, CIAICRB_TB, &interrupt) != NULL) {
		fatal("can't use CIA B Timer B");
	}

	/* this timer is all mine */
	interrupting = 1;

	SetICR(CIAResource, CIAICRF_TB);
	AbleICR(CIAResource, CIAICRF_SETCLR | CIAICRF_TB);
	times_up = 0;
}

void
closetimer()
{
	if (interrupting) {
		ciab.ciacrb &= ~CIACRBF_START;
		AbleICR(CIAResource, CIAICRF_TB);
		RemICRVector(CIAResource, CIAICRB_TB, &interrupt);
		interrupting = 0;
	}
}
