home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff316.lzh
/
Vectors
/
V1.0
/
src
/
ciatimer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-02-06
|
4KB
|
161 lines
#include <exec/types.h>
#include <exec/tasks.h>
#include <exec/interrupts.h>
#include <hardware/cia.h>
#include <hardware/custom.h>
#include <hardware/intbits.h>
#include <resources/cia.h>
#include <stdio.h>
static struct CIA *ciaa = (struct CIA *) 0x00BFE001L;
static struct CIA *ciab = (struct CIA *) 0x00BFD000L;
long CIA_Seconds = 0;
long CIA_Microseconds = 0;
/* timeslice is 46911 intervals. Each interval is 1.397 microseconds,
* this should correspond to a timing interval of 65536 microseconds */
#define CIA_TIME_SLICE ((unsigned short) 46911)
static struct Interrupt
CIATimerInterrupt,
*OldCIAInterrupt = (struct Interrupt *)-1;
static struct Library *CIAResource = NULL;
#define ciatlo ciaa->ciatalo
#define ciathi ciaa->ciatahi
#define ciacr ciaa->ciacra
#define CIAINTBIT CIAICRB_TA
#define CLEAR 0
/* this is the actual interrupt routine. since +p 32-bit model is used,
* no special dinking around is necessary to get a C routine to run as
* an interrupt.
*/
VOID CIAInterrupt()
{
/* increment saved microseconds by number generated between CIA
* interrupts, and if we passed a million, increment seconds */
CIA_Microseconds += 65536;
if (CIA_Microseconds > 1000000)
{
CIA_Seconds++;
CIA_Microseconds -= 1000000;
}
}
/* start the timer, clear pending interrupts, and enable timer A
* Interrupts */
void StartCIATimer()
{
ciacr &= ~(CIACRAF_RUNMODE); /* set it to reload on overflow */
ciacr |= (CIACRAF_LOAD | CIAICRF_TA);
SetICR(CIAResource,CLEAR|CIAICRF_TA);
AbleICR(CIAResource, CIAICRF_SETCLR | CIAICRF_TA);
}
void StopCIATimer()
{
AbleICR(CIAResource, CLEAR | CIAICRF_TA);
ciacr &= ~CIACRAF_START;
}
/* set period between timer increments */
void SetCIATimer(micros)
unsigned short micros;
{
ciatlo = micros & 0xff;
ciathi = micros >> 8;
}
/* stop the timer and remove its interrupt vector */
void EndCIATimer()
{
if (OldCIAInterrupt == NULL)
{
StopCIATimer();
RemICRVector(CIAResource, CIAINTBIT, &CIATimerInterrupt);
}
}
BOOL BeginCIATimer()
{
extern struct Interrupt *AddICRVector();
/* Open the CIA resource */
if ((CIAResource = (struct Library *)OpenResource(CIAANAME)) == NULL)
return(FALSE);
CIATimerInterrupt.is_Node.ln_Type = NT_INTERRUPT;
CIATimerInterrupt.is_Node.ln_Pri = 127;
CIATimerInterrupt.is_Code = CIAInterrupt;
/* install interrupt */
if ((OldCIAInterrupt = AddICRVector(CIAResource,CIAINTBIT,&CIATimerInterrupt)) != NULL)
{
EndCIATimer();
return(FALSE);
}
SetCIATimer(CIA_TIME_SLICE);
StartCIATimer();
return(TRUE);
}
/* return the elapsed real time in seconds and microseconds since the
* cia timer interrupt handler was installed.
*
* ElapsedTime(&secs,µsecs);
*
* with the chosen timeslice interval, every timer interrupt represents
* 65536 microseconds, so the count of interrupts received can be shifted
* and or'ed in. The thing that needs scaling is the timer count we
* read from the hardware registers. It's range of 0 - 46911 1.397
* microsecond ticks must be changed to a range of 0 - 65535 1.0
* microsecond ticks, which is done below
*
* note the code should really read the lo count register again after
* reading the high one and comparing them to be sure it didn't wrap
* in between reads
*
* interrupts are off during this to reduce the possibility of a problem
* with the counter interrupt coming between the cia reads and the big tick
* read, and because it's short it's no biggie, but again it should
* really do more
*/
void ElapsedTime(sec_ptr,usec_ptr)
int *sec_ptr,*usec_ptr;
{
register long seconds, microseconds;
register long ciahi, cialo;
Disable();
ciahi = ciathi;
cialo = ciatlo;
seconds = CIA_Seconds;
microseconds = CIA_Microseconds;
Enable();
/* total microseconds is CIA_BigTicks * 65536 + timerval * 1.397 */
/* to multiply the timer ticks * 1.397, you can multiply by 1430
* and divide by 1024 (or shift right by 10, get it?)
*/
ciahi = CIA_TIME_SLICE - ((ciahi << 8) + cialo);
ciahi = ((ciahi * 1430) >> 10) & 0xffff;
microseconds += ciahi;
if (microseconds > 1000000)
{
microseconds -= 1000000;
seconds++;
}
*sec_ptr = seconds;
*usec_ptr = microseconds;
return;
}