0,0 → 1,140 |
unit Delay; |
|
{-----------------------------------------------------------------} |
{ Definovane spozdeni, ktere funguje i na } |
{ vykonnejsich pocitacich } |
{ } |
{ Verze 1.0 portovano by miho 96 } |
{ 1.1 popora kratkych casu miho 98 } |
{ 1.2 podpora rychlych CPU ( rozsireni DelayCnt1 na DWORD ) } |
{-----------------------------------------------------------------} |
|
{$I-,S-} |
|
interface |
|
|
procedure xDelay(MS: Word); |
{-- cas uveden v milisekundach --} |
|
|
procedure xDelayMicro(MicroS: Word); |
{-- cas uveden v mikrosekundach --} |
{ POZOR: Casy jsou vzdy o neco delsi a za normalnich podminek } |
{ je cas delsi radove o nekolik mikrosekund } |
{ ( na PC Pentium 75 to dela cca 6us ). } |
|
|
implementation |
|
|
var DelayCnt1:longint; { kalibrace casu po 1 ms } |
DelayCnt55:longint; { totez pred vydelenim 55 } |
|
|
procedure DelayLoop; |
begin |
asm |
@@Loop: SUB AX,1 { DX:AX - pocitadlo DWORD } |
SBB DX,0 { dekrement } |
JC @@End { doteklo } |
CMP BL,ES:[DI] { pri uplynuti tiku ( 55ms ) } |
JE @@Loop { taky koncim } |
@@End: |
end; |
end; |
|
|
procedure Initialize; |
{-- inicializace - kalibrace casu --} |
begin |
asm |
MOV AX,40H { adresa bunky BIOS DATA s tiky } |
MOV ES,AX { po 55 ms aktualizuje BIOS } |
MOV DI,6CH |
MOV BL,ES:[DI] |
@@Wait: CMP BL,ES:[DI] |
JE @@Wait { pockej na cely tik } |
MOV BL,ES:[DI] { schovej si tik do BL } |
MOV AX,-28 { piskvorcova konstanta ? asi } |
CWD |
CALL DelayLoop { pockej na konec tiku BL } |
NOT AX { a pocitej cas v DS:AX} |
NOT DX |
MOV word ptr [DelayCnt55],AX { uschovej kalibraci } |
MOV word ptr [DelayCnt55+2],DX |
end; {asm} |
DelayCnt1:=DelayCnt55 div 55; { uschovej kalibraci 1 ms } |
end; {Initialize} |
|
|
procedure xDelay(MS: Word); |
{-- proved standardni spozdeni merene v milisekundach --} |
begin |
asm |
MOV CX,MS { pocet milisekund } |
JCXZ @@End { nulova hodnota - hned konci } |
MOV AX,40H { adresa BIOS COM port - to je } |
MOV ES,AX { jakakoli bunka, ktera se v } |
XOR DI,DI { v provozu nemeni aby se netestoval } |
MOV BL,ES:[DI] { casovac a presto mohla byt } |
@@Loop: MOV AX,word ptr [DelayCnt1] { procedura DelayLoop stejna } |
MOV DX,word ptr [DelayCnt1+2] { DX:AX kalibracni konsatnta } |
CALL DelayLoop { pro spozdeni 1 ms } |
LOOP @@Loop |
@@End: |
end; {asm} |
end; {xDelay} |
|
|
procedure xDelayMicro(MicroS: Word); |
{-- procedura pro spozdeni zadavane v mikrosekundach --} |
label Error; |
begin {-- prepocitej zadany cas na pocet cyklu --} |
asm |
{-- DWORD * WORD / WORD -> DWORD --} |
SUB DX,DX |
MOV AX,WORD PTR[DelayCnt55+2] |
MOV BX,55000 |
MOV CX,MicroS |
DIV BX |
PUSH DX |
MUL CX |
MOV DI,DX |
AND DX,DX |
POP DX |
JNZ Error |
MOV AX,WORD PTR[DelayCnt55] |
DIV BX |
PUSH DX |
MUL CX |
MOV SI,AX |
ADD DI,DX |
POP AX |
JC Error |
MUL CX |
DIV BX |
ADD SI,AX |
ADC DI,0 |
PUSH SI |
PUSH DI |
{-- vlastni spozdeni --} |
MOV AX,40H { opet konstantni bunka } |
MOV ES,AX |
XOR DI,DI |
MOV BL,ES:[DI] |
POP DX { DX:AX cas v poctech cyklu } |
POP AX |
CALL DelayLoop |
end; {asm} |
exit; |
asm |
Error: MOV AX,0FFFFH |
MOV DX,AX |
CALL DelayLoop |
end; {asm} |
end; |
|
|
begin Initialize; { udelej kalibraci } |
end. |