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-}interfaceprocedure 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 ). }implementationvar DelayCnt1:longint; { kalibrace casu po 1 ms }DelayCnt55:longint; { totez pred vydelenim 55 }procedure DelayLoop;beginasm@@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 --}beginasmMOV AX,40H { adresa bunky BIOS DATA s tiky }MOV ES,AX { po 55 ms aktualizuje BIOS }MOV DI,6CHMOV 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 }CWDCALL DelayLoop { pockej na konec tiku BL }NOT AX { a pocitej cas v DS:AX}NOT DXMOV word ptr [DelayCnt55],AX { uschovej kalibraci }MOV word ptr [DelayCnt55+2],DXend; {asm}DelayCnt1:=DelayCnt55 div 55; { uschovej kalibraci 1 ms }end; {Initialize}procedure xDelay(MS: Word);{-- proved standardni spozdeni merene v milisekundach --}beginasmMOV 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,DXMOV AX,WORD PTR[DelayCnt55+2]MOV BX,55000MOV CX,MicroSDIV BXPUSH DXMUL CXMOV DI,DXAND DX,DXPOP DXJNZ ErrorMOV AX,WORD PTR[DelayCnt55]DIV BXPUSH DXMUL CXMOV SI,AXADD DI,DXPOP AXJC ErrorMUL CXDIV BXADD SI,AXADC DI,0PUSH SIPUSH DI{-- vlastni spozdeni --}MOV AX,40H { opet konstantni bunka }MOV ES,AXXOR DI,DIMOV BL,ES:[DI]POP DX { DX:AX cas v poctech cyklu }POP AXCALL DelayLoopend; {asm}exit;asmError: MOV AX,0FFFFHMOV DX,AXCALL DelayLoopend; {asm}end;begin Initialize; { udelej kalibraci }end.