home *** CD-ROM | disk | FTP | other *** search
- /* timer -- real time interval timer for Turbo C */
- /* copyright 1987 Michael M Rubenstein */
-
- /* The technique for chaining to the old interrupt routine is due to */
- /* Don Corbitt */
-
- #include <dos.h>
- #include "atfinish.h"
- #include "timer.h"
-
- #define INT_REGS unsigned bp, unsigned di, unsigned si, unsigned ds, \
- unsigned es, unsigned dx, unsigned cx, unsigned bx, \
- unsigned ax, unsigned ip, unsigned cs, unsigned flags
-
- volatile static long count;
- static int timed_out;
- static void (*timer_func)(void);
- static void interrupt (*old_ticker)(void) = (void interrupt (*) ()) 0;
-
- void clear_timer_routine(void), set_timer_routine(void);
- void interrupt new_ticker(INT_REGS);
-
- extern unsigned _psp;
-
- /* set timer */
- void set_timer(int seconds, void (*func)())
- {
- if (seconds == 0)
- clear_timer_routine();
- else
- {
- timer_func = func;
- set_timer_routine();
- disable();
- count = (long) (seconds * 182l);
- count /= 10l;
- timed_out = 0;
- enable();
- }
- }
-
- /* reset ticker to previous routine */
- static void clear_timer_routine(void)
- {
- if (old_ticker != (void interrupt (*) ()) 0)
- setvect(0x1c, old_ticker);
- }
-
- /* set ticker to timer routine. also set exit address to make sure it gets */
- /* reset if program exits. can't use "atexit" since that is bypassed on */
- /* various types of abnormal termination */
- static void set_timer_routine(void)
- {
- void interrupt (*ticker)(void) = (void interrupt (*) ()) 0;
-
-
- /* set timer routine */
- if (old_ticker == (void interrupt (*)()) 0)
- {
- ticker = getvect(0x1c);
- atfinish(clear_timer_routine);
- }
-
- disable();
- old_ticker = ticker;
- enable();
- setvect(0x1c, new_ticker);
- }
-
- #pragma warn -par
- /* ticker routine. count down and set timed_out when zero is reached */
- static void interrupt new_ticker(INT_REGS)
- {
- volatile unsigned temp[6];
-
- if (--count == 0)
- timed_out = 1;
-
- /* chain to next routine */
- temp[0] = bp; /* Save top 3 values */
- temp[1] = di;
- temp[2] = si;
- bp = ds; /* Move all others up by 3 */
- di = es;
- si = dx;
- ds = cx;
- es = bx;
- dx = ax;
- cx = FP_OFF(old_ticker); /* and put a new ip/cs/flags */
- bx = FP_SEG(old_ticker); /* on the stack */
- ax = flags & ~0x200;
- _BP -= 6; /* Modify BP by three words */
- /* NOTE: after changing _BP, don't */
- /* plan on using an local variables, */
- /* other than those here. */
- bp = temp[3]; /* Restore top 3 values */
- di = temp[4];
- si = temp[5];
- }
- #pragma warn .par
-
- /* check if timer expired and execute timer function if so */
- void chk_timer(void)
- {
- if (timed_out)
- (*timer_func)();
- }
-