(Lightly edited by JRS; not tested) Date: Tue, 7 Mar 2000 00:51:17 -0500 (EST) From: robert rozee To: www.merlyn.demon.co.uk Hi, I was reading the page in your site relating to timing under Turbo Pascal; http://www.merlyn.demon.co.uk/pas-time.htm. Follows are some bits of code that might be of interest or that might wish to incorporate into your page. procedure restf ; { restore interrupt flag from stack } inline( $58/ { pop AX } { get previously pushed flags } $80/$E4/$02/ { and AH,2 } { check interrupt flag } $74/$01/ { jz short $+3 } { skip if was not already set } $FB); { sti } { enable interrupts } The above restores from pushf; cli;, as you mention that popf doesn't restore the interrupt flag under all circumstances. I had previously assumed that popf always worked correctly. function read_count : word ; { read CTC channel 0 count } inline( $30/$C0/ { xor AL,AL } $9C/ { pushf } { save flags status } $FA/ { cli } { disable interrupts (if enabled) } $E6/$43/ { out 43,AL } { latch channel 0 count } $EB/$00/ { jmp short $+2 } { delay for slow I/O } $E4/$40/ { in AL,40 } { get LSB of count } $88/$C4/ { mov AH,AL } { save in AH } $EB/$00/ { jmp short $+2 } { delay for slow I/O } $E4/$40/ { in AL,40 } { get MSB of count } $59/ { pop CX } { get previously pushed flags } $80/$E5/$02/ { and CH,2 } { check interrupt flag } $74/$01/ { jz short $+3 } { skip if was not already set } $FB/ { sti } { enable interrupts } $86/$C4) ; { xchg AL,AH } { swap LSB&MSB to correct order } Reads the channel 0 counter. Only produces useful results if the mode of the counter has been set to pulse, not square wave. procedure load_count(count : word); { load CTC channel 0 count } inline( $EB/$00/ { jmp shout $+2 } { delay for slow I/O } $E6/$40/ { out 40,AL } { load LSB of count } $88/$E0/ { mov AL,AH } $EB/$00/ { jmp short $+2 } { delay for slow I/O } $E6/$40) ; { out 40,AL } { load MSB of count } Puts required jump delays between out instructions. Used thus: port[$40] := $36 ; load_counter(1193) ; Recently I've been using this to reprogram the count on-the-fly (without the port[$40] line!) within the interrupt handler, selecting between 1193 and 1194 divisors to get an exact 1 ms interrupt rate. I use a variation on Bresenham's line drawing algorithm to select which divisor to use. ms := ticks*54 ; inc(ms, ticks div 2) ; inc(ms, ticks div 3) ; inc(ms, ticks div 11) ; inc(ms, ticks div 798) ; This is what I use to convert 18.2Hz timer tick counter into milliseconds. Seems to work OK, although the values returned are not going to be 'evenly' spaced. Any suggestions for a better solution? { JRS : yes - *55, Dec div 6 - & others } {$R-} var biostime : longint absolute $0040:$006C ; H, M, S : byte ; L : longint ; W : word absolute L ; begin L := biostime ; { longint counter at } Dec(L, L div 196629) ; { 0040h:006Ch which counts } H := L div 65543 ; { to 1573040 every 24 hours } L := L mod 65543 ; { is converted to H,M,S by } Dec(L, L div 2849) ; { subtracting a correction } M := W div 1092 ; { based on quotent before } W := W mod 1092 ; { main divisions. Note that } Dec(W, W div 90) ; { L maps over W so that when } S := W div 18; { L<65536, then W==L. } Writeln(H:4, M:4, S:4) ; end. I've been using the above for a _very_ long time to convert timer ticks into hours/minutes/seconds, although I think I prefer the method given on your web site. ... robert rozee, christchurch, new zealand ----------------