From: Raul Kompass Newsgroups: comp.os.msdos.djgpp Subject: ultra precise timing < 80 usecs Date: Wed, 18 Sep 1996 12:17:34 -0700 Organization: University Leipzig Lines: 117 Message-ID: <32404ACE.2A88@server1.rz.uni-leipzig.de> Reply-To: kompass AT server1 DOT rz DOT uni-leipzig DOT de NNTP-Posting-Host: kogn5.psychologie.uni-leipzig.de Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Hello! For my experiments I needed a very precise timing and found code (for Borland-C), that combines the information from timer-interrupts in the BIOS (1/16 sec's precision IMO) with the value of the counters in the CTC that provide the timer-interrupt. Thus you have a way to get ultra-precise time (about 1 usec precision). You cannot control something at that precision because the interrupts getting fired regularly occupy chunks of 50 to 90 usecs on a 386 or better PC. But you can have definitely that precision and you can measure the precision during the experiments. I would like to have that functionality in djgpp. There is a solution to speed up the timer-interrupt but I think it's too complicated and has a lot of overhead. I would like to have the timer-interrupt as fast as possible (unchanged), and a better implementation of the ***** gettimeofday() ***** function that does not use the CTC at present. The code I append below does this in assembler. I can transform it to gas but I don't know the interrupt-handling in djgpp's protected mode. You have to disable the timer-interrupt to prevent that you read the bios-value and before you get the CTC-value the bios and CTC are updated. Can anybody help me please with this problem? ********************************************************************* initializetimer() and restoretimer() aren't necessary I believe because the CTC is already programmed in the right way. But I'm not sure. void initializetimer(void) { outp(0x043,0x034); _asm\ { jmp short NullJump1 NullJump1:; } outp(0x040,0x000); _asm\ { jmp short NullJump2 NullJump2:; } outp(0x040,0x000); } void restoretimer(void) { outp(0x043,0x036); _asm\ { jmp short NullJump1 NullJump1:; } outp(0x040,0x000); _asm\ { jmp short NullJump2 NullJump2:; } outp(0x040,0x000); } #define TimerResolution 1193UL #define Seconds (1000*TimerResolution) /* not absolutely exact */ #pragma warn -rvl /* shut up Turbo C warning about return value */ long readtimer(void) { _asm\ { cli /* Disable interrupts */ mov dx,020h /* Address PIC ocw3 */ mov al,00Ah /* Ask to read irr */ out dx,al mov al,00h /* Latch timer 0 */ out 043h,al in al,dx /* Read irr */ mov di,ax /* Save it in DI */ in al,040h /* Counter --> bx*/ mov bl,al /* LSB in BL */ in al,040h mov bh,al /* MSB in BH */ not bx /* Need ascending counter */ in al,021h /* Read PIC imr */ mov si,ax /* Save it in SI */ mov al,00FFh /* Mask all interrupts */ out 021h,al mov ax,040h /* read low word of time */ mov es,ax /* from BIOS data area */ mov dx,es:[06Ch] mov ax,si /* Restore imr from SI */ out 021h,al sti /* Enable interrupts */ mov ax,di /* Retrieve old irr */ test al,001h /* Counter hit 0? */ jz done /* Jump if not */ cmp bx,0FFh /* Counter > 0x0FF? */ ja done /* Done if so */ inc dx /* Else count int req. */ done:; mov ax,bx /* set function result */ } } #pragma warn .rvl /* reset Turbo C return value warning */ ********************************************************** thanks Raul kompass AT server1 DOT rz DOT uni-leipzig DOT de