Category : C Source Code
Archive   : R386DEV4.ZIP
Filename : TIMER.C

 
Output of file : TIMER.C contained in archive : R386DEV4.ZIP
/* Timer routines for REND386; written by Dave Stampe, July 1992 */

/* Copyright 1992 by Dave Stampe and Bernie Roehl.
May be freely used to write software for release into the public domain;
all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
for permission to incorporate any part of this software into their
products!
*/

#include
#include
#include
#include
#include
#include

/******************* TIMER INTERRUPT STUFF ****************/

#define TIMER_VECT 8 /* timer chip int. vector */
#define UNUSED_VECT 128 /* user vector: used to link to std ISR */

#define PIC_CMD 0x20 /* constants for PIC EOI command */
#define NONSPEC_EOI 0x20
#define TIMER_MODE 0x34 /* timer setup command */
#define TIMER_CONTROL 0x43 /* timer control register port */
#define TIMER_0 0x40 /* timer 0 port */

#define LATCH_COUNT 0x00 /* command to latch count */

#define SYNC_INTERVAL 5 /* how many frames between resynchronization */

static void init_SG_timer(int time);
static void reset_SG_timer();

static void interrupt fast_SG_timer();
static void interrupt (*oldint)() = NULL; /* old timer ISR vector */

static unsigned int clock_rate = 0; /* calibrated timer rate for vertical */
static unsigned int clock_rate_hi = 0;
static unsigned int clock_rate_lo = 0;

static unsigned int divisor = 0; /* counter to emulate 18.2 Hz tick */

static int syncount = SYNC_INTERVAL; /* resync counter */

static long int_timer = 0; /* incremented each frame (use for timing) */

static void (*frame_interrupt_routine)() = NULL;
static void (*glove_interrupt_routine)() = NULL;

static int glovecount = 0;
static int glove_rate = 2; /* count of how many glove calls per frame */

/******************* FIND VERTICAL FRAME RATE *************/

#define ADVANCE 100 /* time (microseconds) of advance */
/* in vert. interrupt. Will act as */

static int find_sega_speed() /* "vertical hold" adjustment */
{
unsigned int old, new; /* Routine to compute vertical frame */

vsync();
outportb(TIMER_CONTROL, TIMER_MODE);
outportb(TIMER_0, 0);
outportb(TIMER_0, 0); /* timer must count modulo 65536 */

disable(); /* time of vert. retrace */
vsync();
outportb(TIMER_CONTROL,LATCH_COUNT);
enable();
old = inportb(TIMER_0) & 0xFF;
old |= (inportb(TIMER_0) << 8);

vsync(); /* time 2 vert. retraces later */
disable();
vsync();
outportb(TIMER_CONTROL,LATCH_COUNT);
enable();
new = inportb(TIMER_0) & 0xFF;
new |= (inportb(TIMER_0) << 8);

return ((old-new)>>1) - ADVANCE; /* compute interrupt rate */
}


long current_time()
{
long i;

disable();
i = int_timer;
enable();
return i;
}

void set_current_time(long i)
{
disable();
int_timer = i;
enable();
}


volatile int interrupts_occurred = 0;

static void interrupt fast_SG_timer() /* NEW TIMER ISR */
{
unsigned int olddiv = divisor;

disable();

int_timer++;
interrupts_occurred++;

if (frame_interrupt_routine == NULL) goto glove;
else frame_interrupt_routine(glovecount-1);
if (--glovecount <= 0) glovecount = glove_rate;
else goto glove;


syncount--;
if (syncount < 0)
{
syncount = SYNC_INTERVAL;
outportb(TIMER_CONTROL, TIMER_MODE); /* stop timer */
outportb(TIMER_0, 255);
outportb(TIMER_0, 255);
enable();
disable();
vsync();
outportb(TIMER_CONTROL, TIMER_MODE); /* restart timer */
outportb(TIMER_0, clock_rate_lo);
outportb(TIMER_0, clock_rate_hi);
}


glove:

if (glove_interrupt_routine) glove_interrupt_routine();
divisor += clock_rate; /* dec divide count */
if (divisor < olddiv) /* simulate 18.2 Hz ISR if time */
geninterrupt(UNUSED_VECT);

outportb(PIC_CMD, NONSPEC_EOI);
enable();
}


static int ticks_per_second = 0;

int get_ticks_per_second()
{
return ticks_per_second;
}

static void reset_SG_timer();

static void init_SG_timer(int speed) /* SET UP FAST TIMER */
{
atexit(reset_SG_timer); /* set traps for error, ctrl c, */
signal(SIGABRT, reset_SG_timer);
signal(SIGFPE, reset_SG_timer);
signal(SIGINT, reset_SG_timer);

clock_rate = speed; /* save speed for future work */
ticks_per_second = 1190000L/speed;
clock_rate_hi = clock_rate >> 8;
clock_rate_lo = clock_rate & 255;

divisor = 0; /* set up timers */
syncount = SYNC_INTERVAL;
int_timer = 0;

if (getvect(UNUSED_VECT) == NULL)
{ /* setup int's if required(first run) */
disable();
oldint = getvect(TIMER_VECT); /* setup ISR vectors */
setvect(UNUSED_VECT,oldint);
setvect(TIMER_VECT, fast_SG_timer);
outportb(TIMER_CONTROL, TIMER_MODE); /* load timer */
outportb(TIMER_0, clock_rate_lo);
outportb(TIMER_0, clock_rate_hi);
enable();
}
}


static void reset_SG_timer() /* RESET PC TO NORMAL */
{
disable();
setvect(TIMER_VECT, oldint); /* reset vector */
outportb(TIMER_CONTROL, TIMER_MODE); /* reset timer */
outportb(TIMER_0, 0);
outportb(TIMER_0, 0);
setvect(UNUSED_VECT,NULL); /* disconnect flag */
enable();

signal(SIGINT, SIG_DFL);
signal(SIGABRT, SIG_DFL);
signal(SIGFPE, SIG_DFL);
}

/* SET EVERYTHING UP */
/* (init. glove, Sega first) */

void init_SG_interrupt( void (*sega_switcher)(), /* NULL if no sega/video */
void (*glove_handler)(), /* NULL if no glove driver */
int glove_tc) /* 1.19*uS (test interval) */
{ /* 6500 sugg. ALWAYS (fast timer) */
int i_rate;

glove_interrupt_routine = glove_handler;
frame_interrupt_routine = sega_switcher;

if (sega_switcher == NULL)
i_rate = glove_tc; /* glove only: use suggested speed */
else
{
i_rate = find_sega_speed(); /* use a multiple of video rate */
if (glove_tc != 0)
{
glove_rate = i_rate/glove_tc; /* about 2x for 72 fps, 3x for 60 */

if (glove_rate < 1) glove_rate = 1; /* handle no glove driver */
if (glove_rate > 20) glove_rate = 20; /* come on now... */
i_rate /= glove_rate;
}
else i_rate /=3;
}
init_SG_timer(i_rate); /* start 'er up! */
}

void init_timer()
{
init_SG_interrupt(NULL,NULL,6500);
}



  3 Responses to “Category : C Source Code
Archive   : R386DEV4.ZIP
Filename : TIMER.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/