I work on a program that transfer some data via the LPT port. I need to use
very short delays, but can't figure out how to do them less than 1 us. I
will run the program on different machines and the best results should be to
use interrupts. But how ?
I appreciate any help from you. :)
/Per-Erik
____________________________________________
Per Erik Klarenfjord
Third Base Electronics
Triogatan 7
656 36 KARLSTAD
you cant. something to do with bus clock speed or something. I did the same
with a linux box recently and also ran into the problem. Its explained in
one of the io.c or io.h files.
The 16 bit register used for the 18ms DOS/Windows ticks at 0.8xx us
You can get small delays pooling this register. Let's say 400us.
So, 400/0.8xx ~= 500. Get the reg value + 500 and keep comparing
until you have a >=. Watch out this register wrap from 0xFFFF to
0x0000
JSouto
>
> I work on a program that transfer some data via the LPT port. I need to use
> very short delays, but can't figure out how to do them less than 1 us. I
> will run the program on different machines and the best results should be to
> use interrupts. But how ?
> I appreciate any help from you. :)
>
> /Per-Erik
>
> ____________________________________________
>
> Per Erik Klarenfjord
> Third Base Electronics
> Triogatan 7
> 656 36 KARLSTAD
>
> Tel: 054-837852 070-3975147
> E-mail: .....pererikKILLspam@spam@3base.net
>
> http://www.3base.net
Thanks a lot.
Do you know the address to that (0.8xxx us) register ?
I noticed some very interesting pages in a book i have.
The code can be used with 286, 386, 486 and Pentium....
To create a processor independent delay, IBM made PB4 pf port 61h toggle
every 15.085 us. That means that by monitoring PB4 of port 61h, a fixed time
delay can be obtained, as shown next from IBM PC AT BIOS. Upon entering this
subroutine called WAITF, register CX must hold the number of 15.085 us time
delays needed.
;CX = Count of 15,085 us
WAITF PROC NEAR
PUSH AX
WAITF1:
IN AL,61h
AND AL,10h ;Check PB4
CMP AL,AH ;Did it just change ?
JE WAITF1 ;Wait for Change
MOV AH,AL ;Save the new PB4 Status
LOOP WAITF1 ;Continue until CX becomes 0
POP AX
RET
WAITF ENDP
Example, to create a half-second delay, set CX=33144 (33144 * 15,085 us) =
1/2 second, and then call the above routine as done by IBM PC AT BIOS.
The 16 bit register used for the 18ms DOS/Windows ticks at 0.8xx us
You can get small delays pooling this register. Let's say 400us.
So, 400/0.8xx ~= 500. Get the reg value + 500 and keep comparing
until you have a >=. Watch out this register wrap from 0xFFFF to
0x0000
JSouto
PerErik Klarenfjord wrote:
>
> I work on a program that transfer some data via the LPT port. I need to
use
> very short delays, but can't figure out how to do them less than 1 us. I
> will run the program on different machines and the best results should be
to {Quote hidden}
> use interrupts. But how ?
> I appreciate any help from you. :)
>
> /Per-Erik
>
> ____________________________________________
>
> Per Erik Klarenfjord
> Third Base Electronics
> Triogatan 7
> 656 36 KARLSTAD
>
> Tel: 054-837852 070-3975147
> E-mail: pererikKILLspam3base.net
>
> http://www.3base.net
part 0 5100 bytes > Thanks a lot.
> Do you know the address to that (0.8xxx us) register ?
The system timer is port $43. There are a number of "gotcha"s.
* It is an 8-bit device! You have to use a latch command to read it.
* Later machines are not "IBM compatible" - when they "virutalised" the
timer chip from the earlier machines, they decided to alter it a bit,
make it "simpler" etc. There are some tricks about it I haven't full
documentation on.
* All timing routines will be distorted by interrupts. Only code based
on reading the system timer (or keyboard chip as you mention) will be
less severely affected. The system timer is used by Windoze to task
switch. If you let it roll over, not only do you have to adjust the
count, but you likely lose control for 1/18 of a second at least.
* The timer counts *down*.
Possible approach, as per attached test code: Wait until the timer has
recently rolled over (value about 65000 or so), then initiate the
action to be timed, wait for a correspondingly lesser timer count, and
finish the timed action. The test code (which does not print out the
result until after the time delay finishes) suggests this will be about
99% reliable. If gross overrun 1% of the time doesn't matter, this will
work. If you can't accept the overrun, use external hardware.
> To create a processor independent delay, IBM made PB4 pf port 61h
> toggle every 15.085 us. That means that by monitoring PB4 of port 61h,
> a fixed time delay can be obtained, as shown next from IBM PC AT BIOS.
That'll be the keyboard controller. Presumably works still in current
machines, but same problems as system timer.
> The 16 bit register used for the 18ms DOS/Windows ticks at 0.8xx us
> You can get small delays pooling this register. Let's say 400us.
> So, 400/0.8xx ~= 500. Get the reg value + 500 and keep comparing
> until you have a >=.
Wrong way. It counts DOWN.
> Watch out this register wrap from 0xFFFF to 0x0000
Yes - as above!
--
Cheers,
Paul B.
\\ INTTEST1.SEQ Light Chaser Test ver:1.00 14/10/98 P.B. Webster
{ ' noop alias immediate
DEFINED TARGET-INIT NIP \ Are we target compiling?
0<> #IF
' \ alias \F immediate ' noop alias \T immediate
#ELSE
' noop alias \F immediate ' \ alias \T immediate
#ENDIF
\ ***************************************************************************
decimal
$278 VALUE PORT
VARIABLE TIMER $40 TIMER !
$6C.0040 2CONSTANT times
VARIABLE PRVTIME
VARIABLE TTIME
code RTIME ( -- time ) \ read system timer
\T CLEAR_LABELS
\T SAVE_BX
mov dx, timer \ point to timer
add dx, # 3 \ control register
sub al, al \ timer zero
out dx, al \ latched
sub dx, # 3 \ timer zero
in al, dx \ get the byte
mov ah, al \ hide it
in al, dx \ get secnd byte
xchg al, ah \ swap them
\F 1push
\T MOV BX, AX
\T RET
end-code
: TICK? ( --- f ) \ has a tick passed?
times @L dup prvtime @ -
if dup prvtime ! $FF00 or else drop false then ;
: PARTICK? ( delay --- f ) \ has a partial tick passed?
rtime ttime @ over -
rot > if dup ttime ! else drop false then ;
: WAITICK BEGIN TICK? UNTIL ;
: WAITQTC BEGIN $4000 PARTICK? UNTIL ;
: PPUT ( c --- ) \ write to parallel port
port pc! ;
: PGET ( --- c ) \ read parallel port
port pc@ ;
: CPUT ( c --- ) \ write to control register
$0B xor port 2+ pc! ;
: CGET ( --- c ) \ read control register
port 2+ pc@ $0B xor ;
part 0 177 bytes PerErik Klarenfjord wrote:
>
> Thanks a lot.
> Do you know the address to that (0.8xxx us) register ?
Attachment converted: wonderland:Delay.zip (pZIP/pZIP) (00018049)
You are right (as always, I see). Digging my files I
found the Delay stuff I used and the hole thing counts
down. I used to set the 16 bit register (Counter #2)
with the desired delay value and wait until it gets <= zero.
Sorry for the wrong info.
JSouto
>
> PerErik Klarenfjord wrote:
> .....
> > The 16 bit register used for the 18ms DOS/Windows ticks at 0.8xx us
> > You can get small delays pooling this register. Let's say 400us.
> > So, 400/0.8xx ~= 500. Get the reg value + 500 and keep comparing
> > until you have a >=.
>
> Wrong way. It counts DOWN.
>
> > Watch out this register wrap from 0xFFFF to 0x0000
>
> Yes - as above!
> --
> Cheers,
> Paul B.