From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/SNIP/uclock.c | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100755 reference/C/CONTRIB/SNIP/uclock.c (limited to 'reference/C/CONTRIB/SNIP/uclock.c') diff --git a/reference/C/CONTRIB/SNIP/uclock.c b/reference/C/CONTRIB/SNIP/uclock.c new file mode 100755 index 0000000..0b0058c --- /dev/null +++ b/reference/C/CONTRIB/SNIP/uclock.c @@ -0,0 +1,106 @@ +/* +** UCLOCK.C +** +** Contains routines to perform microsecond accuracy timing +** operations. +** +** Adapted from public domain source originally by David L. Fox +** Modified by Bob Stout +*/ + +#include "uclock.h" + +/* Constants */ + +#define CONTVAL 0x34 /* == 00110100 Control byte for 8253 timer. */ + /* Sets timer 0 to 2-byte read/write, */ + /* mode 2, binary. */ +#define T0DATA 0x40 /* Timer 0 data port address. */ +#define TMODE 0x43 /* Timer mode port address. */ +#define BIOS_DS 0x40 /* BIOS data segment. */ +#define B_TIKP 0x6c /* Address of BIOS (18.2/s) tick count. */ +#define SCALE 10000 /* Scale factor for timer ticks. */ + +/* The following values assume 18.2 BIOS ticks per second resulting from + the 8253 being clocked at 1.19 MHz. */ + +#define us_BTIK 54925 /* Micro sec per BIOS clock tick. */ +#define f_BTIK 4595 /* Fractional part of usec per BIOS tick. */ +#define us_TTIK 8381 /* Usec per timer tick * SCALE. (4/4.77 MHz) */ + +static int init = 0; + +/* +** usec_clock() +** +** An analog of the clock() function, usec_clock() returns a number of +** type uclock_t (defined in UCLOCK.H) which represents the number of +** microseconds past midnight. Analogous to CLK_TCK is UCLK_TCK, the +** number which a usec_clock() reading must be divided by to yield +** a number of seconds. +*/ + +uclock_t usec_clock(void) +{ + unsigned char msb, lsb; + unsigned int tim_ticks; + static uclock_t last, init_count; + static uclock_t far *c_ptr; + uclock_t count, us_tmp; + + if (!init) + { + c_ptr = (uclock_t far *)MK_FP(BIOS_DS, B_TIKP); + init = 1; /* First call, we have to set up timer. */ + int_off(); + outp(TMODE, CONTVAL); /* Write new control byte. */ + outp(T0DATA, 0); /* Initial count = 65636. */ + outp(T0DATA, 0); + init_count = *c_ptr; + int_on(); + return 0; /* First call returns zero. */ + } + + /* Read PIT channel 0 count - see text */ + + int_off(); /* Don't want an interrupt while getting time. */ + outp(TMODE, 0); /* Latch count. */ + lsb = (unsigned char)inp(T0DATA); /* Read count. */ + msb = (unsigned char)inp(T0DATA); + + /* Get BIOS tick count (read BIOS ram directly for speed and + to avoid turning on interrupts). */ + + count = *c_ptr; + int_on(); /* Interrupts back on. */ + if ((-1) == init) /* Restart count */ + { + init_count = count; + init = 1; + } + + /* Merge PIT channel 0 count with BIOS tick count */ + + if (count < init_count) + count += last; + else last = count; + count -= init_count; + tim_ticks = (unsigned)(-1) - ((msb << 8) | lsb); + us_tmp = count * us_BTIK; + return (us_tmp + ((long)tim_ticks * us_TTIK + us_tmp % SCALE) / SCALE); +} + +/* +** restart_uclock() +** +** Since usec_clock() bases its return value on a differential value, +** a potential exists for problems in programs which run continuously +** for more than 24 hours. In such an application, it's necessary, at +** least once a day, to reset usec_clock's starting count. +*/ + +void restart_uclock(void) +{ + if (init) + init = -1; +} -- cgit v1.2.3-54-g00ecf