From: jih-shin ho Subject: Timer subroutine To: djgpp AT sun DOT soe DOT clarkson DOT edu (djgpp) Date: Wed, 14 Jul 93 10:29:18 EAT Hi: Here is the timer subroutines I use. The original subroutines are for Turbo-C. I modify them to make them work with djgpp. You can find the original version in M_SEC12.ZIP at SIMTEL20 mirror sites. These subroutines DO NOT affect system timing. The time between start and stop must be less than one hour. Allow multiple read_timer() calls between timer_on() and timer_off(). Usage: #include "timer.h" ..... timer_on(); /* Start timer */ ..... start = read_timer(); ..... stop = read_timer(); timer_off(); time_passed = elapsed_time(start,stop); /* unit = msec */ count_passed = elapsed_count(start,stop); /* unit = clock pulse */ /* time_passed is equal to (count_passed / TIMER_MILLI_COUNT) */ -- Jih-Shin Ho ----------------------------- #ifndef _TIMER_H #define _TIMER_H /* timer.h * Include file defining the timer routines. * Include this file in any program using them. */ #define TIMER_COUNT 1193181u /* Clock freq. = 1.193181 MHz */ #define TIMER_MILLI_COUNT 1193u /*Calculate time elapsed (in milliseconds) between Start and Stop*/ unsigned int elapsed_time(unsigned int start, unsigned int stop); /*Reprogram the timer chip to allow 1 millisecond resolution*/ extern void timer_on(void); /*Restore the timer chip to its normal state*/ extern void timer_off(void); /*Read the timer */ extern unsigned int read_timer(void); extern unsigned int elapsed_count(unsigned int start, unsigned int stop); #endif ---------------------- /* ;timer.s ;Assembly language functions extracted from TIMER.C ;and recoded in *real* assembly language. ;(Too many incompatibilities in all the different ;implementations of inline assembly language ;-) ; ;David Kirschbaum ;Toad Hall ; ;Modified for DJGPP by Jih-Shin Ho, 1993 ; u7711501 AT bicmos DOT ee DOT nctu DOT edu DOT tw */ .text .align 2,0x90 .globl _timer_on .globl _timer_off .globl _read_timer .globl _elapsed_time .globl _elapsed_count /* ;void timer_on(void) */ _timer_on: movb $0x34,%al jmp LCommon ;/* common to return */ /* ;void timer_off(void) */ _timer_off: movb $0x36,%al ;/* outp(0x043,0x036); */ LCommon: movw $0x43,%dx outb %al,%dx jmp L1 L1: movw $0x40,%dx ;/* outp(0x040,0x000); */ xorw %ax,%ax outb %al,%dx jmp L2 L2: outb %al,%dx ;/* outp(0x040,0x000); */ ret .align 2,0x90 /* ;unsigned long read_timer(void) */ _read_timer: xorl %eax,%eax movl %eax,%edx movl %eax,%ecx outb %al,$0x43 ;/* Latch timer 0 */ movw (0xe000046c),%dx inb $0x40,%al ;/* Counter --> CX */ movb %al,%cl ;/* LSB in CL */ inb $0x40,%al movb %al,%ch ;/* MSB in CH */ notw %cx ;/* Need ascending counter */ movw %dx,%ax shll $16,%eax orl %ecx,%eax ret .bss .lcomm flag,1 .text .align 2,0x90 /* unsigned int elapsed_time(start,stop) */ _elapsed_count: movb $0,flag jmp L4 .align 2,0x90 _elapsed_time: movb $1,flag L4: movl 8(%esp),%edx ;/* stop */ movl 4(%esp),%ecx ;/* start */ movl %edx,%eax subl %ecx,%eax jae L3 movl $-1,%eax subl %ecx,%eax addl %edx,%eax incl %eax movl %eax,%ecx andl $0xffff0000,%ecx cmpl $0xffff0000,%ecx jne L3 andl $0xffff,%eax L3: testb $1,flag jz L5 movl $1193,%ecx xorl %edx,%edx divl %ecx L5: ret