/*--------------------------- timer.c --------------------------------- */ /* */ /* Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au) */ /* Date: Jan 1994 */ /* Version: 22 January 1994 */ /* */ /* This one comes from FLy8, it simply reads the timer chip and then */ /* converts it to microseconds. */ /* */ /* This program is released into the public domain. */ /* */ /*--------------------------------------------------------------------- */ #include #include #include /* #include "pc8254.h" */ /* --------------------------------- pc8254.h ------------------------------- */ /* Definitions for the timer chip 8254. Used for timekeeping and speaker * control. */ #define CHANNEL_0 0x0040 /* system tick */ #define CHANNEL_2 0x0042 /* speaker tone */ #define COMMAND_REG 0x0043 #define WRITE_CH0 0x0036 #define WRITE_CH2 0x00b6 #define READ_SPECIAL 0x00c2 #define PORT_B 0x0061 /* speaker on/off control */ #define XTAL 1193182L #define TIMER_MODES 0x000e #define TIMER_MODE 0x0002 #define TIMER_OUT 0x0080 #define TIMER_PERIOD 0x0000ffffL /* this is the standard */ /* --------------------------------- pc8254.h end---------------------------- */ typedef unsigned short Ushort; typedef unsigned int Uint; typedef unsigned long Ulong; /* These are the timer reading support functions. */ static Ushort near disable (void) { Ushort flags; _asm { pushf pop flags cli } return (flags); } static void near enable (Ushort flags) { _asm { push flags popf } } static Ulong timer_period = TIMER_PERIOD; extern Ushort far get_timer (void) { Ushort t, status, flags; do { flags = disable (); outp (COMMAND_REG, READ_SPECIAL); status = (Ushort) inp (CHANNEL_0); /* get status */ t = (Ushort)inp (CHANNEL_0); /* low byte */ t += (Ushort)(inp (CHANNEL_0) << 8); /* high byte */ enable (flags); } while (0 == t); if ((status & TIMER_MODES) == TIMER_MODE*3) { t >>= 1; if (status & TIMER_OUT) t += (Ushort)((timer_period+1)/2); } return ((Ushort)(timer_period - t)); /* make it count up */ } extern Ulong far timer_micros (Ushort old, Ushort new) { Ushort ticks; if (new >= old) ticks = new - old; else ticks = (new+timer_period) - old; if (ticks > (Ushort)4000) return ((Ulong)ticks * (Ulong)4000L / (Ulong)(XTAL/(1000L/4L))); else return ((Ulong)ticks * (Ulong)1000000L / (Ulong)XTAL); }